mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-07 05:53:06 +00:00
chat: file transfer rework
This commit is contained in:
parent
8db69e481d
commit
6a0aba483f
15 changed files with 316 additions and 466 deletions
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
|
|
|||
|
|
@ -40,8 +40,12 @@
|
|||
}
|
||||
}
|
||||
// also add current entry, if not listed
|
||||
if (![_contacts containsObject:filter]) {
|
||||
[_contacts insertObject:filter atIndex:0];
|
||||
const LinphoneAddress *addr = linphone_core_interpret_url([LinphoneManager getLc], filter.UTF8String);
|
||||
char *uri = linphone_address_as_string(addr);
|
||||
NSString *nsuri = [NSString stringWithUTF8String:uri];
|
||||
ms_free(uri);
|
||||
if (![_contacts containsObject:nsuri]) {
|
||||
[_contacts insertObject:nsuri atIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -64,11 +68,17 @@
|
|||
cell = [[UIChatCreateCell alloc] initWithIdentifier:kCellId];
|
||||
}
|
||||
|
||||
cell.addressLabel.text = _contacts[indexPath.row];
|
||||
const LinphoneAddress *addr =
|
||||
linphone_core_interpret_url([LinphoneManager getLc], cell.addressLabel.text.UTF8String);
|
||||
[ContactDisplay setDisplayNameLabel:cell.displayNameLabel forAddress:addr];
|
||||
|
||||
linphone_core_interpret_url([LinphoneManager getLc], ((NSString *)_contacts[indexPath.row]).UTF8String);
|
||||
if (addr) {
|
||||
char *uri = linphone_address_as_string(addr);
|
||||
cell.addressLabel.text = [NSString stringWithUTF8String:uri];
|
||||
ms_free(uri);
|
||||
[ContactDisplay setDisplayNameLabel:cell.displayNameLabel forAddress:addr];
|
||||
} else {
|
||||
cell.displayNameLabel.text = _contacts[indexPath.row];
|
||||
cell.addressLabel.text = NSLocalizedString(@"Invalid address", nil);
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
@implementation ChatConversationTableView
|
||||
|
||||
@synthesize chatRoomDelegate;
|
||||
|
||||
#pragma mark - Lifecycle Functions
|
||||
|
||||
- (void)dealloc {
|
||||
|
|
@ -181,7 +179,7 @@
|
|||
cell = [[NSClassFromString(kCellId) alloc] initWithIdentifier:kCellId];
|
||||
}
|
||||
[cell setChatMessage:chat];
|
||||
[cell setChatRoomDelegate:chatRoomDelegate];
|
||||
[cell setChatRoomDelegate:_chatRoomDelegate];
|
||||
[super accessoryForCell:cell atPath:indexPath];
|
||||
return cell;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,31 +23,21 @@
|
|||
#import "UITextViewNoDefine.h"
|
||||
#import "FileTransferDelegate.h"
|
||||
#import "ChatConversationTableView.h"
|
||||
#import "UIChatBubbleTextCell.h"
|
||||
|
||||
@interface UIChatBubblePhotoCell : UITableViewCell
|
||||
@interface UIChatBubblePhotoCell : UIChatBubbleTextCell
|
||||
|
||||
//@property(nonatomic, strong) IBOutlet UIView *innerView;
|
||||
//@property(nonatomic, strong) IBOutlet UIView *bubbleView;
|
||||
//@property(nonatomic, strong) IBOutlet UIImageView *backgroundImage;
|
||||
//@property(nonatomic, strong) IBOutlet UITextViewNoDefine *messageText;
|
||||
//@property(nonatomic, strong) IBOutlet UILoadingImageView *messageImageView;
|
||||
//@property(nonatomic, strong) IBOutlet UIButton *deleteButton;
|
||||
//@property(nonatomic, strong) IBOutlet UILabel *dateLabel;
|
||||
//@property(nonatomic, strong) IBOutlet UIImageView *statusImage;
|
||||
//@property(nonatomic, strong) IBOutlet UIButton *downloadButton;
|
||||
//@property(weak, nonatomic) IBOutlet UIProgressView *fileTransferProgress;
|
||||
//@property(weak, nonatomic) IBOutlet UIButton *cancelButton;
|
||||
//@property(nonatomic, strong) id<ChatConversationDelegate> chatRoomDelegate;
|
||||
//
|
||||
//+ (CGFloat)height:(LinphoneChatMessage *)chatMessage width:(int)width;
|
||||
//
|
||||
//- (void)setChatMessage:(LinphoneChatMessage *)message;
|
||||
//- (void)connectToFileDelegate:(FileTransferDelegate *)ftd;
|
||||
//
|
||||
//- (IBAction)onDeleteClick:(id)event;
|
||||
//- (IBAction)onDownloadClick:(id)event;
|
||||
//- (IBAction)onImageClick:(id)event;
|
||||
//- (IBAction)onCancelDownloadClick:(id)sender;
|
||||
//- (IBAction)onResendClick:(id)event;
|
||||
@property(nonatomic, strong) IBOutlet UILoadingImageView *messageImageView;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *downloadButton;
|
||||
@property(weak, nonatomic) IBOutlet UIProgressView *fileTransferProgress;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *cancelButton;
|
||||
@property(weak, nonatomic) IBOutlet UIView *imageSubView;
|
||||
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)message;
|
||||
- (void)connectToFileDelegate:(FileTransferDelegate *)ftd;
|
||||
- (IBAction)onDownloadClick:(id)event;
|
||||
- (IBAction)onImageClick:(id)event;
|
||||
- (IBAction)onCancelClick:(id)sender;
|
||||
- (IBAction)onResendClick:(id)event;
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -25,247 +25,124 @@
|
|||
#import <AssetsLibrary/ALAssetRepresentation.h>
|
||||
|
||||
@implementation UIChatBubblePhotoCell {
|
||||
LinphoneChatMessage *message;
|
||||
FileTransferDelegate *ftd;
|
||||
}
|
||||
#if 0
|
||||
|
||||
|
||||
static const CGFloat CELL_MIN_HEIGHT = 50.0f;
|
||||
static const CGFloat CELL_MIN_WIDTH = 150.0f;
|
||||
static const CGFloat CELL_MESSAGE_X_MARGIN = 26.0f + 10.0f;
|
||||
static const CGFloat CELL_MESSAGE_Y_MARGIN = 36.0f;
|
||||
static const CGFloat CELL_FONT_SIZE = 17.0f;
|
||||
static const CGFloat CELL_IMAGE_HEIGHT = 100.0f;
|
||||
static const CGFloat CELL_IMAGE_WIDTH = 100.0f;
|
||||
static UIFont *CELL_FONT = nil;
|
||||
|
||||
#pragma mark - Lifecycle Functions
|
||||
|
||||
- (id)initWithIdentifier:(NSString *)identifier {
|
||||
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
|
||||
[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil];
|
||||
|
||||
#if 0
|
||||
// shift message box, otherwise it will collide with the bubble
|
||||
CGRect messageCoords = _messageText.frame;
|
||||
messageCoords.origin.x += 2;
|
||||
messageCoords.origin.y += 2;
|
||||
messageCoords.size.width -= 5;
|
||||
|
||||
_messageText.frame = messageCoords;
|
||||
_messageText.allowSelectAll = TRUE;
|
||||
#endif
|
||||
// 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
|
||||
// correctly adapt its height too
|
||||
UIView *sub = nil;
|
||||
for (int i = 0; i < arrayOfViews.count; i++) {
|
||||
if ([arrayOfViews[i] isKindOfClass:UIView.class]) {
|
||||
sub = arrayOfViews[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
[self setFrame:CGRectMake(0, 0, sub.frame.size.width, sub.frame.size.height)];
|
||||
[self addSubview:sub];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self setChatMessage:NULL];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)amessage {
|
||||
if (amessage == message) {
|
||||
if (amessage == self.message) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self disconnectFromFileDelegate];
|
||||
_messageImageView.image = nil;
|
||||
_fileTransferProgress.progress = 0;
|
||||
|
||||
if (message) {
|
||||
linphone_chat_message_unref(message);
|
||||
linphone_chat_message_set_user_data(message, NULL);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(message), NULL);
|
||||
}
|
||||
|
||||
message = amessage;
|
||||
if (amessage) {
|
||||
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);
|
||||
|
||||
const LinphoneContent *c = linphone_chat_message_get_file_transfer_information(message);
|
||||
const LinphoneContent *c = linphone_chat_message_get_file_transfer_information(amessage);
|
||||
if (c) {
|
||||
const char *name = linphone_content_get_name(c);
|
||||
for (FileTransferDelegate *aftd in [[LinphoneManager instance] fileTransferDelegates]) {
|
||||
if (linphone_chat_message_get_file_transfer_information(aftd.message) &&
|
||||
strcmp(name, linphone_content_get_name(
|
||||
linphone_chat_message_get_file_transfer_information(aftd.message))) == 0) {
|
||||
LOGI(@"Chat message [%p] with file transfer delegate [%p], connecting to it!", message, aftd);
|
||||
linphone_chat_message_get_file_transfer_information(amessage))) == 0) {
|
||||
LOGI(@"Chat message [%p] with file transfer delegate [%p], connecting to it!", amessage, aftd);
|
||||
[self connectToFileDelegate:aftd];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[self update];
|
||||
}
|
||||
}
|
||||
|
||||
+ (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 *)textMessage {
|
||||
return [self.class TextMessageForChat:message];
|
||||
[super setChatMessage:amessage];
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
if (message == nil) {
|
||||
LOGW(@"Cannot update message room cell: null message");
|
||||
[super update];
|
||||
if (self.message == nil) {
|
||||
LOGW(@"Cannot update message room cell: NULL message");
|
||||
return;
|
||||
}
|
||||
const char *url = linphone_chat_message_get_external_body_url(message);
|
||||
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(self.message);
|
||||
if (state == LinphoneChatMessageStateDelivered || state == LinphoneChatMessageStateNotDelivered) {
|
||||
if (ftd) {
|
||||
[ftd stopAndDestroy];
|
||||
ftd = nil;
|
||||
}
|
||||
}
|
||||
|
||||
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(message);
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:message];
|
||||
(url && (strstr(url, "http") == url)) || linphone_chat_message_get_file_transfer_information(self.message);
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:self.message];
|
||||
|
||||
// this is an image (either to download or already downloaded)
|
||||
if (is_external || localImage) {
|
||||
if (localImage) {
|
||||
if (_messageImageView.image == nil) {
|
||||
NSURL *imageUrl = [NSURL URLWithString:localImage];
|
||||
_messageText.hidden = YES;
|
||||
[_messageImageView startLoading];
|
||||
__block LinphoneChatMessage *achat = message;
|
||||
[LinphoneManager.instance.photoLibrary assetForURL:imageUrl
|
||||
resultBlock:^(ALAsset *asset) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
|
||||
^(void) {
|
||||
if (achat == message) { // Avoid glitch and scrolling
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:[asset thumbnail]];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_messageImageView setImage:image];
|
||||
[_messageImageView setFullImageUrl:asset];
|
||||
[_messageImageView stopLoading];
|
||||
_messageImageView.hidden = NO;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
failureBlock:^(NSError *error) {
|
||||
LOGE(@"Can't read image");
|
||||
}];
|
||||
}
|
||||
if (ftd.message != nil) {
|
||||
_cancelButton.hidden = NO;
|
||||
_fileTransferProgress.hidden = NO;
|
||||
_downloadButton.hidden = YES;
|
||||
} else {
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = YES;
|
||||
}
|
||||
} else {
|
||||
_messageText.hidden = YES;
|
||||
_messageImageView.hidden = _cancelButton.hidden = _fileTransferProgress.hidden = (ftd.message == nil);
|
||||
_downloadButton.hidden = !_cancelButton.hidden;
|
||||
assert(is_external || localImage);
|
||||
if (localImage) {
|
||||
// we did not load the image yet, so start doing so
|
||||
if (_messageImageView.image == nil) {
|
||||
NSURL *imageUrl = [NSURL URLWithString:localImage];
|
||||
[_messageImageView startLoading];
|
||||
__block LinphoneChatMessage *achat = self.message;
|
||||
[LinphoneManager.instance.photoLibrary assetForURL:imageUrl
|
||||
resultBlock:^(ALAsset *asset) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
|
||||
^(void) {
|
||||
if (achat == self.message) { // Avoid glitch and scrolling
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:[asset thumbnail]];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_messageImageView setImage:image];
|
||||
[_messageImageView setFullImageUrl:asset];
|
||||
[_messageImageView stopLoading];
|
||||
_messageImageView.hidden = NO;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
failureBlock:^(NSError *error) {
|
||||
LOGE(@"Can't read image");
|
||||
}];
|
||||
}
|
||||
// simple text message
|
||||
} else {
|
||||
[_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 */
|
||||
|
||||
NSAttributedString *attr_text =
|
||||
[[NSAttributedString alloc] initWithString:self.textMessage
|
||||
attributes:@{
|
||||
NSFontAttributeName : [UIFont systemFontOfSize:17.0],
|
||||
NSForegroundColorAttributeName : [UIColor darkGrayColor]
|
||||
}];
|
||||
_messageText.attributedText = attr_text;
|
||||
_messageImageView.hidden = YES;
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = YES;
|
||||
}
|
||||
|
||||
// Date
|
||||
_dateLabel.text =
|
||||
[LinphoneUtils timeToString:linphone_chat_message_get_time(message) withStyle:NSDateFormatterMediumStyle];
|
||||
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(message);
|
||||
BOOL outgoing = linphone_chat_message_is_outgoing(message);
|
||||
|
||||
if (!outgoing) {
|
||||
[_statusImage setAccessibilityValue:@"incoming"];
|
||||
_statusImage.hidden = TRUE; // not useful for incoming chats..
|
||||
} else if (state == LinphoneChatMessageStateInProgress) {
|
||||
[_statusImage setImage:[UIImage imageNamed:@"chat_message_inprogress.png"]];
|
||||
[_statusImage setAccessibilityValue:@"in progress"];
|
||||
_statusImage.hidden = FALSE;
|
||||
} else if (state == LinphoneChatMessageStateDelivered || state == LinphoneChatMessageStateFileTransferDone) {
|
||||
[_statusImage setImage:[UIImage imageNamed:@"chat_message_delivered.png"]];
|
||||
[_statusImage setAccessibilityValue:@"delivered"];
|
||||
_statusImage.hidden = FALSE;
|
||||
} else {
|
||||
[_statusImage setImage:[UIImage imageNamed:@"chat_message_not_delivered.png"]];
|
||||
[_statusImage setAccessibilityValue:@"not delivered"];
|
||||
_statusImage.hidden = FALSE;
|
||||
|
||||
NSAttributedString *resend_text =
|
||||
[[NSAttributedString alloc] initWithString:NSLocalizedString(@"Resend", @"Resend")
|
||||
attributes:@{NSForegroundColorAttributeName : [UIColor redColor]}];
|
||||
[_dateLabel setAttributedText:resend_text];
|
||||
}
|
||||
|
||||
if (outgoing) {
|
||||
[_messageText setAccessibilityLabel:@"Outgoing message"];
|
||||
} else {
|
||||
[_messageText setAccessibilityLabel:@"Incoming message"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setEditing:(BOOL)editing {
|
||||
[self setEditing:editing animated:FALSE];
|
||||
}
|
||||
|
||||
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
|
||||
if (animated) {
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
[UIView setAnimationDuration:0.3];
|
||||
}
|
||||
_deleteButton.hidden = !editing;
|
||||
if (animated) {
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - View Functions
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
if (message != nil) {
|
||||
BOOL is_outgoing = linphone_chat_message_is_outgoing(message);
|
||||
CGRect innerFrame;
|
||||
innerFrame.size = [self.class viewSize:message width:[self frame].size.width];
|
||||
innerFrame.origin.y = 0.0f;
|
||||
innerFrame.origin.x = is_outgoing ? self.frame.size.width - innerFrame.size.width : 0;
|
||||
_innerView.frame = innerFrame;
|
||||
|
||||
CGRect messageFrame = _bubbleView.frame;
|
||||
messageFrame.origin.y = (_innerView.frame.size.height - messageFrame.size.height) / 2;
|
||||
if (!is_outgoing) {
|
||||
messageFrame.origin.y += 5;
|
||||
// we are uploading the image
|
||||
if (ftd.message != nil) {
|
||||
_cancelButton.hidden = NO;
|
||||
_fileTransferProgress.hidden = NO;
|
||||
_downloadButton.hidden = YES;
|
||||
} else {
|
||||
messageFrame.origin.y -= 5;
|
||||
_cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = YES;
|
||||
}
|
||||
_backgroundImage.image =
|
||||
is_outgoing ? [UIImage imageNamed:@"chat_bubble_outgoing"] : [UIImage imageNamed:@"chat_bubble_incoming"];
|
||||
_bubbleView.frame = messageFrame;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Action Functions
|
||||
|
||||
- (IBAction)onDeleteClick:(id)event {
|
||||
if (message != NULL) {
|
||||
[ftd cancel];
|
||||
UITableView *tableView = VIEW(ChatConversationView).tableController.tableView;
|
||||
NSIndexPath *indexPath = [tableView indexPathForCell:self];
|
||||
[tableView.dataSource tableView:tableView
|
||||
commitEditingStyle:UITableViewCellEditingStyleDelete
|
||||
forRowAtIndexPath:indexPath];
|
||||
// we must download the image: either it has already started (show cancel button) or not yet (show download
|
||||
// button)
|
||||
} else {
|
||||
// CGRect newFrame = _imageSubView.frame;
|
||||
// newFrame.origin.y = _messageImageView.frame.origin.y + ((ftd.message == nil) ? 0 :
|
||||
//_messageImageView.frame.size.height);
|
||||
// _imageSubView.frame = newFrame;
|
||||
_messageImageView.hidden = _cancelButton.hidden = (ftd.message == nil);
|
||||
_downloadButton.hidden = !_cancelButton.hidden;
|
||||
_fileTransferProgress.hidden = NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -273,20 +150,25 @@ static UIFont *CELL_FONT = nil;
|
|||
[ftd cancel];
|
||||
ftd = [[FileTransferDelegate alloc] init];
|
||||
[self connectToFileDelegate:ftd];
|
||||
[ftd download:message];
|
||||
[ftd download:self.message];
|
||||
_cancelButton.hidden = NO;
|
||||
_downloadButton.hidden = YES;
|
||||
}
|
||||
|
||||
- (IBAction)onCancelDownloadClick:(id)sender {
|
||||
- (IBAction)onCancelClick:(id)sender {
|
||||
FileTransferDelegate *tmp = ftd;
|
||||
[self disconnectFromFileDelegate];
|
||||
[tmp cancel];
|
||||
_fileTransferProgress.progress = 0;
|
||||
[self update];
|
||||
}
|
||||
|
||||
- (void)onResendClick:(id)event {
|
||||
[super onResendClick:event];
|
||||
}
|
||||
|
||||
- (IBAction)onImageClick:(id)event {
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(message);
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(self.message);
|
||||
if (state == LinphoneChatMessageStateNotDelivered) {
|
||||
[self onResendClick:event];
|
||||
} else {
|
||||
|
|
@ -300,69 +182,6 @@ static UIFont *CELL_FONT = nil;
|
|||
}
|
||||
}
|
||||
|
||||
- (IBAction)onResendClick:(id)event {
|
||||
if (message == nil)
|
||||
return;
|
||||
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(message);
|
||||
if (state == LinphoneChatMessageStateNotDelivered) {
|
||||
if (linphone_chat_message_get_file_transfer_information(message) != NULL) {
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:message];
|
||||
NSURL *imageUrl = [NSURL URLWithString:localImage];
|
||||
|
||||
[self onDeleteClick:nil];
|
||||
|
||||
[[LinphoneManager instance]
|
||||
.photoLibrary assetForURL:imageUrl
|
||||
resultBlock:^(ALAsset *asset) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
|
||||
^(void) {
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:[asset thumbnail]];
|
||||
[_chatRoomDelegate startImageUpload:image url:imageUrl];
|
||||
});
|
||||
}
|
||||
failureBlock:^(NSError *error) {
|
||||
LOGE(@"Can't read image");
|
||||
}];
|
||||
} else {
|
||||
[self onDeleteClick:nil];
|
||||
|
||||
double delayInSeconds = 0.4;
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
|
||||
[_chatRoomDelegate resendChat:self.textMessage withExternalUrl:nil];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma mark - State changed handling
|
||||
static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
|
||||
UIChatBubblePhotoCell *thiz = (__bridge UIChatBubblePhotoCell *)linphone_chat_message_get_user_data(msg);
|
||||
LOGI(@"State for message [%p] changed to %s", msg, linphone_chat_message_state_to_string(state));
|
||||
if (linphone_chat_message_get_file_transfer_information(msg) != NULL) {
|
||||
if (state == LinphoneChatMessageStateDelivered || state == LinphoneChatMessageStateNotDelivered) {
|
||||
// we need to refresh the tableview because the filetransfer delegate unreffed
|
||||
// the message message before state was LinphoneChatMessageStateFileTransferDone -
|
||||
// if we are coming back from another view between unreffing and change of state,
|
||||
// the transient message will not be found and it will not appear in the list of
|
||||
// message, so we must refresh the table when we change to this state to ensure that
|
||||
// all transient messages apppear
|
||||
// ChatRoomViewController *controller = DYNAMIC_CAST(
|
||||
// [PhoneMainView.instance changeCurrentView:ChatRoomViewController.compositeViewDescription
|
||||
// push:TRUE],
|
||||
// ChatRoomViewController);
|
||||
// [controller.tableController setChatRoom:linphone_chat_message_get_chat_room(msg)];
|
||||
// This is breaking interface too much, it must be fixed in file transfer cb.. meanwhile, disabling it.
|
||||
|
||||
if (thiz->ftd) {
|
||||
[thiz->ftd stopAndDestroy];
|
||||
thiz->ftd = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
[thiz update];
|
||||
}
|
||||
|
||||
#pragma mark - LinphoneFileTransfer Notifications Handling
|
||||
|
||||
- (void)connectToFileDelegate:(FileTransferDelegate *)aftd {
|
||||
|
|
@ -389,9 +208,9 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
|
|||
|
||||
if (state == LinphoneChatMessageStateInProgress) {
|
||||
float progress = [[[notif userInfo] objectForKey:@"progress"] floatValue];
|
||||
// When uploading a file, the message file is first uploaded to the server,
|
||||
// When uploading a file, the self.message file is first uploaded to the server,
|
||||
// so we are in progress state. Then state goes to filetransfertdone. Then,
|
||||
// the exact same message is sent to the other participant and we come
|
||||
// the exact same self.message is sent to the other participant and we come
|
||||
// back to in progress again. This second time is NOT an upload, so we must
|
||||
// not update progress!
|
||||
_fileTransferProgress.progress = MAX(_fileTransferProgress.progress, progress);
|
||||
|
|
@ -410,6 +229,25 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
|
|||
[self update];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (CGSize)viewSizeWithWidth:(int)width {
|
||||
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 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.statusImage.frame.size.width + 5) + MARGIN_WIDTH;
|
||||
bubbleSize.height = messageSize.height + MARGIN_HEIGHT;
|
||||
|
||||
return bubbleSize;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -1,102 +1,125 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UIChatBubblePhotoCell">
|
||||
<connections>
|
||||
<outlet property="avatarImage" destination="hD2-19-7IH" id="N1B-Jn-wTo"/>
|
||||
<outlet property="backgroundColorImage" destination="U2P-5n-gg8" id="1Hn-bx-mua"/>
|
||||
<outlet property="bottomBarColor" destination="6dA-3U-OPW" id="xJX-pe-zlu"/>
|
||||
<outlet property="bubbleView" destination="UGz-WT-BUv" id="8qr-kw-dSx"/>
|
||||
<outlet property="cancelButton" destination="6dl-Nz-rdv" id="ygz-nv-omC"/>
|
||||
<outlet property="contactDateLabel" destination="JyR-RQ-uwF" id="Tc4-9t-i5V"/>
|
||||
<outlet property="downloadButton" destination="N75-gL-R6t" id="EgN-Ab-Ded"/>
|
||||
<outlet property="fileTransferProgress" destination="USm-wC-GvG" id="POt-YD-NCG"/>
|
||||
<outlet property="imageSubView" destination="GmN-7v-uuO" id="k9r-Xc-csv"/>
|
||||
<outlet property="messageImageView" destination="yMW-cT-bpU" id="MNr-F2-abQ"/>
|
||||
<outlet property="statusImage" destination="hSL-MF-B9b" id="cwm-bV-O3a"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="qHD-cv-2vc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="159"/>
|
||||
<view contentMode="scaleToFill" id="UGz-WT-BUv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="334" height="140"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" usesAttributedText="YES" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="Tzq-H4-Xn9" userLabel="contactDateLabel">
|
||||
<rect key="frame" x="66" y="8" width="246" height="19"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
||||
<attributedString key="attributedText">
|
||||
<fragment content="11:35 John ">
|
||||
<attributes>
|
||||
<color key="NSColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<font key="NSFont" size="16" name="HelveticaNeue"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="truncatingTail" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
<fragment content="Doe">
|
||||
<attributes>
|
||||
<color key="NSColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<font key="NSFont" size="16" name="HelveticaNeue-Bold"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="truncatingTail" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
</attributedString>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="avatar.png" id="6V0-NH-dBG" userLabel="avatarImage" customClass="UIRoundedImageView">
|
||||
<rect key="frame" x="8" y="5" width="50" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
||||
<accessibilityTraits key="traits" none="YES" image="YES" notEnabled="YES"/>
|
||||
<bool key="isElement" value="YES"/>
|
||||
</accessibility>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" id="1ze-V7-Vi5" userLabel="textView">
|
||||
<rect key="frame" x="66" y="30" width="246" height="129"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<view clipsSubviews="YES" contentMode="scaleToFill" id="Y7i-Gm-AdY" userLabel="innerView">
|
||||
<rect key="frame" x="6" y="5" width="322" height="130"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="Placeholder text is another very long ipsem lum dolorem...and it continues" id="Hnc-55-etE" userLabel="messageText">
|
||||
<rect key="frame" x="0.0" y="0.0" width="246" height="121"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" id="GmN-7v-uuO" userLabel="imageView">
|
||||
<rect key="frame" x="66" y="30" width="246" height="129"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" id="USm-wC-GvG" userLabel="transferProgress">
|
||||
<rect key="frame" x="4" y="93" width="238" height="2"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</progressView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="128 Ko / 172 Ko" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Aaa-MV-yvm" userLabel="fileSizeLabel">
|
||||
<rect key="frame" x="4" y="73" width="238" height="12"/>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.20000000298023224" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="color_A.png" id="U2P-5n-gg8" userLabel="backgroundColorImage">
|
||||
<rect key="frame" x="0.0" y="0.0" width="322" height="130"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="avatar.png" id="hD2-19-7IH" userLabel="avatarImage" customClass="UIRoundedImageView">
|
||||
<rect key="frame" x="7" y="1" width="40" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Contact avatar">
|
||||
<accessibilityTraits key="traits" none="YES" image="YES" notEnabled="YES"/>
|
||||
<bool key="isElement" value="YES"/>
|
||||
</accessibility>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" usesAttributedText="YES" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" id="JyR-RQ-uwF" userLabel="contactDateLabel">
|
||||
<rect key="frame" x="48" y="0.0" width="246" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<accessibility key="accessibilityConfiguration" label="Contact name"/>
|
||||
<attributedString key="attributedText">
|
||||
<fragment content="11:35 John ">
|
||||
<attributes>
|
||||
<color key="NSColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<font key="NSFont" size="16" name="HelveticaNeue"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="truncatingTail" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
<fragment content="Doe">
|
||||
<attributes>
|
||||
<color key="NSColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<font key="NSFont" size="16" name="HelveticaNeue-Bold"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="truncatingTail" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
</attributedString>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splashscreen.png" id="yMW-cT-bpU" userLabel="image" customClass="UILoadingImageView">
|
||||
<rect key="frame" x="48" y="24" width="274" height="67"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<gestureRecognizers/>
|
||||
</imageView>
|
||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="128 Ko / 172 Ko" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Aaa-MV-yvm" userLabel="fileSizeLabel">
|
||||
<rect key="frame" x="24" y="59" width="274" height="12"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splashscreen.png" id="yMW-cT-bpU" userLabel="image">
|
||||
<rect key="frame" x="8" y="0.0" width="230" height="65"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<gestureRecognizers/>
|
||||
<connections>
|
||||
<outletCollection property="gestureRecognizers" destination="aDF-hC-ddO" appends="YES" id="4oe-Ga-fHE"/>
|
||||
</connections>
|
||||
<view contentMode="scaleToFill" id="GmN-7v-uuO" userLabel="imageSubView">
|
||||
<rect key="frame" x="48" y="91" width="274" height="32.000000029802322"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" id="USm-wC-GvG" userLabel="transferProgress">
|
||||
<rect key="frame" x="10" y="0.0" width="254" height="2"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
</progressView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="N75-gL-R6t" userLabel="transferButton" customClass="UIRoundBorderedButton">
|
||||
<rect key="frame" x="75" y="4.0000000298023224" width="124" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<state key="normal" title="DOWNLOAD">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onDownloadClick:" destination="-1" eventType="touchUpInside" id="8BO-9E-iOX"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="6dl-Nz-rdv" userLabel="cancelButton" customClass="UIRoundBorderedButton">
|
||||
<rect key="frame" x="75" y="4.0000000298023224" width="124" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<state key="normal" title="CANCEL">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onCancelClick:" destination="-1" eventType="touchUpInside" id="D9y-vf-I4Y"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="chat_message_inprogress.png" id="hSL-MF-B9b" userLabel="statusImage">
|
||||
<rect key="frame" x="307" y="0.0" width="15" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="color_A.png" id="6dA-3U-OPW" userLabel="bottomBarColor">
|
||||
<rect key="frame" x="0.0" y="129" width="322" height="1"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</imageView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="N75-gL-R6t" userLabel="transferButton" customClass="UIRoundBorderedButton">
|
||||
<rect key="frame" x="0.0" y="98" width="124" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="DOWNLOAD">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
</button>
|
||||
</subviews>
|
||||
<connections>
|
||||
<outletCollection property="gestureRecognizers" destination="5ZI-Ip-lGl" appends="YES" id="zzJ-Rp-wx6"/>
|
||||
</connections>
|
||||
</view>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="chat_message_inprogress.png" id="x07-o6-6s0" userLabel="messageStatusImage">
|
||||
<rect key="frame" x="305" y="0.0" width="15" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="339" y="43.5"/>
|
||||
<point key="canvasLocation" x="-95" y="166"/>
|
||||
</view>
|
||||
<tapGestureRecognizer id="aDF-hC-ddO" userLabel="imageClick">
|
||||
<connections>
|
||||
|
|
@ -110,9 +133,10 @@
|
|||
</tapGestureRecognizer>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="avatar.png" width="261" height="261"/>
|
||||
<image name="chat_message_inprogress.png" width="12" height="12"/>
|
||||
<image name="splashscreen.png" width="185" height="169"/>
|
||||
<image name="avatar.png" width="255" height="255"/>
|
||||
<image name="chat_message_inprogress.png" width="11" height="12"/>
|
||||
<image name="color_A.png" width="1" height="1"/>
|
||||
<image name="splashscreen.png" width="181" height="165"/>
|
||||
</resources>
|
||||
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
||||
<simulatedStatusBarMetrics key="statusBar"/>
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
@interface UIChatBubbleTextCell : UITableViewCell
|
||||
|
||||
@property(readonly, nonatomic) LinphoneChatMessage *message;
|
||||
@property(nonatomic, weak) IBOutlet UIImageView *backgroundColorImage;
|
||||
@property(nonatomic, weak) IBOutlet UIRoundedImageView *avatarImage;
|
||||
@property(nonatomic, weak) IBOutlet UILabel *contactDateLabel;
|
||||
|
|
@ -40,7 +41,9 @@
|
|||
|
||||
- (IBAction)onDeleteClick:(id)event;
|
||||
- (IBAction)onResendClick:(id)event;
|
||||
- (void)update;
|
||||
|
||||
+ (NSString *)TextMessageForChat:(LinphoneChatMessage *)message;
|
||||
- (CGSize)computeBoundingBox:(NSString *)text size:(CGSize)size font:(UIFont *)font;
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -24,9 +24,7 @@
|
|||
#import <AssetsLibrary/ALAsset.h>
|
||||
#import <AssetsLibrary/ALAssetRepresentation.h>
|
||||
|
||||
@implementation UIChatBubbleTextCell {
|
||||
LinphoneChatMessage *message;
|
||||
}
|
||||
@implementation UIChatBubbleTextCell
|
||||
|
||||
#pragma mark - Lifecycle Functions
|
||||
|
||||
|
|
@ -50,60 +48,63 @@
|
|||
#pragma mark -
|
||||
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)amessage {
|
||||
if (amessage == message) {
|
||||
if (amessage == _message) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (message) {
|
||||
linphone_chat_message_unref(message);
|
||||
linphone_chat_message_set_user_data(message, NULL);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(message), NULL);
|
||||
if (_message) {
|
||||
linphone_chat_message_unref(_message);
|
||||
linphone_chat_message_set_user_data(_message, NULL);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), NULL);
|
||||
}
|
||||
|
||||
message = amessage;
|
||||
_message = amessage;
|
||||
if (amessage) {
|
||||
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);
|
||||
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 *)textMessage {
|
||||
return [self.class TextMessageForChat:message];
|
||||
return [self.class TextMessageForChat:_message];
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
if (message == nil) {
|
||||
LOGW(@"Cannot update message room cell: null message");
|
||||
if (_message == nil) {
|
||||
LOGW(@"Cannot update _message room cell: null _message");
|
||||
return;
|
||||
}
|
||||
[_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 */
|
||||
|
||||
NSAttributedString *attr_text =
|
||||
[[NSAttributedString alloc] initWithString:self.textMessage
|
||||
attributes:@{
|
||||
NSFontAttributeName : _messageText.font,
|
||||
NSForegroundColorAttributeName : [UIColor darkGrayColor]
|
||||
}];
|
||||
_messageText.attributedText = attr_text;
|
||||
if (_messageText) {
|
||||
[_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 */
|
||||
|
||||
NSAttributedString *attr_text =
|
||||
[[NSAttributedString alloc] initWithString:self.textMessage
|
||||
attributes:@{
|
||||
NSFontAttributeName : _messageText.font,
|
||||
NSForegroundColorAttributeName : [UIColor darkGrayColor]
|
||||
}];
|
||||
_messageText.attributedText = attr_text;
|
||||
}
|
||||
|
||||
// Date
|
||||
_contactDateLabel.text = [NSString
|
||||
stringWithFormat:@"%@ - %@", [LinphoneUtils timeToString:linphone_chat_message_get_time(message)
|
||||
stringWithFormat:@"%@ - %@", [LinphoneUtils timeToString:linphone_chat_message_get_time(_message)
|
||||
withStyle:NSDateFormatterShortStyle],
|
||||
[FastAddressBook displayNameForAddress:linphone_chat_message_get_peer_address(message)]];
|
||||
[FastAddressBook displayNameForAddress:linphone_chat_message_get_peer_address(_message)]];
|
||||
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(message);
|
||||
BOOL outgoing = linphone_chat_message_is_outgoing(message);
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(_message);
|
||||
BOOL outgoing = linphone_chat_message_is_outgoing(_message);
|
||||
|
||||
_backgroundColorImage.image = _bottomBarColor.image = [UIImage imageNamed:(outgoing ? @"color_A" : @"color_D")];
|
||||
if (!outgoing) {
|
||||
|
|
@ -129,9 +130,9 @@
|
|||
}
|
||||
|
||||
if (outgoing) {
|
||||
[_messageText setAccessibilityLabel:@"Outgoing message"];
|
||||
[_messageText setAccessibilityLabel:@"Outgoing _message"];
|
||||
} else {
|
||||
[_messageText setAccessibilityLabel:@"Incoming message"];
|
||||
[_messageText setAccessibilityLabel:@"Incoming _message"];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +147,7 @@
|
|||
#pragma mark - Action Functions
|
||||
|
||||
- (IBAction)onDeleteClick:(id)event {
|
||||
if (message != NULL) {
|
||||
if (_message != NULL) {
|
||||
UITableView *tableView = VIEW(ChatConversationView).tableController.tableView;
|
||||
NSIndexPath *indexPath = [tableView indexPathForCell:self];
|
||||
[tableView.dataSource tableView:tableView
|
||||
|
|
@ -156,13 +157,13 @@
|
|||
}
|
||||
|
||||
- (IBAction)onResendClick:(id)event {
|
||||
if (message == nil)
|
||||
if (_message == nil)
|
||||
return;
|
||||
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(message);
|
||||
LinphoneChatMessageState state = linphone_chat_message_get_state(_message);
|
||||
if (state == LinphoneChatMessageStateNotDelivered) {
|
||||
if (linphone_chat_message_get_file_transfer_information(message) != NULL) {
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:message];
|
||||
if (linphone_chat_message_get_file_transfer_information(_message) != NULL) {
|
||||
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:_message];
|
||||
NSURL *imageUrl = [NSURL URLWithString:localImage];
|
||||
|
||||
[self onDeleteClick:nil];
|
||||
|
|
@ -199,56 +200,46 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
|
|||
|
||||
#pragma mark - Bubble size computing
|
||||
|
||||
- (CGSize)computeBoundingBox:(NSString *)text size:(CGSize)size font:(UIFont *)font {
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
|
||||
if ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 7) {
|
||||
return [text boundingRectWithSize:size
|
||||
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
|
||||
attributes:@{
|
||||
NSFontAttributeName : font
|
||||
}
|
||||
context:nil]
|
||||
.size;
|
||||
}
|
||||
#endif
|
||||
{ return [text sizeWithFont:font constrainedToSize:size lineBreakMode:NSLineBreakByCharWrapping]; }
|
||||
}
|
||||
|
||||
- (CGSize)viewSizeWithWidth:(int)width {
|
||||
static const CGFloat TEXT_MIN_HEIGHT = 32.;
|
||||
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 IMAGE_HEIGHT = 100.0f; // TODO: move that in bubblephoto
|
||||
static const CGFloat IMAGE_HEIGHT = 100.0f;
|
||||
static const CGFloat IMAGE_WIDTH = 100.0f;
|
||||
static const CGFloat CHECK_BOX_WIDTH = 40;
|
||||
|
||||
CGSize messageSize, dateSize;
|
||||
int messageAvailableWidth = width - MARGIN_WIDTH - CHECK_BOX_WIDTH;
|
||||
|
||||
const char *url = linphone_chat_message_get_external_body_url(message);
|
||||
if (url == nil && linphone_chat_message_get_file_transfer_information(message) == NULL) {
|
||||
NSString *text = [UIChatBubbleTextCell TextMessageForChat:message];
|
||||
const char *url = linphone_chat_message_get_external_body_url(_message);
|
||||
NSString *text = [UIChatBubbleTextCell TextMessageForChat:_message];
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
|
||||
if ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 7) {
|
||||
messageSize =
|
||||
[text boundingRectWithSize:CGSizeMake(messageAvailableWidth, CGFLOAT_MAX)
|
||||
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
|
||||
attributes:@{
|
||||
NSFontAttributeName : _messageText.font
|
||||
}
|
||||
context:nil]
|
||||
.size;
|
||||
dateSize = [_contactDateLabel.text boundingRectWithSize:_contactDateLabel.frame.size
|
||||
options:(NSStringDrawingUsesLineFragmentOrigin |
|
||||
|
||||
NSStringDrawingUsesFontLeading)
|
||||
attributes:@{
|
||||
NSFontAttributeName : _contactDateLabel.font
|
||||
}
|
||||
context:nil]
|
||||
.size;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
messageSize = [text sizeWithFont:_messageText.font
|
||||
constrainedToSize:CGSizeMake(messageAvailableWidth, CGFLOAT_MAX)
|
||||
lineBreakMode:NSLineBreakByCharWrapping];
|
||||
dateSize = [_contactDateLabel.text sizeWithFont:_contactDateLabel.font
|
||||
constrainedToSize:_contactDateLabel.frame.size
|
||||
lineBreakMode:NSLineBreakByCharWrapping];
|
||||
}
|
||||
} else {
|
||||
CGSize messageSize;
|
||||
if (url != nil || linphone_chat_message_get_file_transfer_information(_message) != NULL) {
|
||||
messageSize = CGSizeMake(IMAGE_WIDTH, IMAGE_HEIGHT);
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
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];
|
||||
|
||||
CGSize bubbleSize;
|
||||
bubbleSize.width = MAX(messageSize.width, dateSize.width + _statusImage.frame.size.width + 5) + MARGIN_WIDTH;
|
||||
|
|
@ -259,9 +250,9 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
|
|||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
if (message != nil) {
|
||||
if (_message != nil) {
|
||||
UITableView *tableView = VIEW(ChatConversationView).tableController.tableView;
|
||||
BOOL is_outgoing = linphone_chat_message_is_outgoing(message);
|
||||
BOOL is_outgoing = linphone_chat_message_is_outgoing(_message);
|
||||
CGRect bubbleFrame = _bubbleView.frame;
|
||||
bubbleFrame.size = [self viewSizeWithWidth:self.frame.size.width];
|
||||
bubbleFrame.origin.x =
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *m
|
|||
// this is the last time we will be notified, so destroy ourselve
|
||||
if (remaining <= size) {
|
||||
LOGI(@"Upload ended");
|
||||
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(thiz.message), NULL);
|
||||
thiz.message = NULL;
|
||||
[thiz stopAndDestroy];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 0efd4dfd5b37fb28ba1ecbabcc8d37defddfd517
|
||||
Subproject commit c9e603882c3b6bd2b387f17ba8c003ffb4f218fe
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 4e3ea86c90cf125f1348dc4f296540d1696e5851
|
||||
Subproject commit 34d3a0583b69946d35b4c7e968530e359423603f
|
||||
Loading…
Add table
Reference in a new issue