mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-03 04:26:27 +00:00
Chat: fix message state icon by reworking file transfer a bit and add simultanous uploads/downloads tests
This commit is contained in:
parent
5991aef599
commit
9d000cdfb9
8 changed files with 133 additions and 68 deletions
|
|
@ -41,8 +41,6 @@
|
|||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
[TUNinePatchCache flushCache]; // Clear cache
|
||||
// [self clearMessageList];
|
||||
// chatRoom = NULL;
|
||||
}
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
|
@ -70,7 +68,7 @@
|
|||
linphone_chat_room_get_peer_address(chatRoom) &&
|
||||
linphone_chat_message_is_outgoing(ftd.message)) {
|
||||
LOGI(@"Appending transient upload message %p", ftd.message);
|
||||
self->messageList = ms_list_append(self->messageList, ftd.message);
|
||||
self->messageList = ms_list_append(self->messageList, linphone_chat_message_ref(ftd.message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -549,7 +549,6 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
|
|||
|
||||
- (BOOL)chatRoomStartImageUpload:(UIImage*)image url:(NSURL*)url{
|
||||
FileTransferDelegate * fileTransfer = [[FileTransferDelegate alloc] init];
|
||||
[[[LinphoneManager instance] fileTransferDelegates] addObject:fileTransfer];
|
||||
[fileTransfer upload:image withURL:url forChatRoom:chatRoom];
|
||||
[tableController addChatEntry:linphone_chat_message_ref(fileTransfer.message)];
|
||||
[tableController scrollToBottom:true];
|
||||
|
|
|
|||
|
|
@ -86,22 +86,44 @@ static UIFont *CELL_FONT = nil;
|
|||
|
||||
- (void)dealloc {
|
||||
[self disconnectFromFileDelegate];
|
||||
if (self->chat) {
|
||||
linphone_chat_message_unref(self->chat);
|
||||
linphone_chat_message_set_user_data(self->chat, NULL);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(self->chat), NULL);
|
||||
self->chat = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)setChatMessage:(LinphoneChatMessage *)message {
|
||||
if (message != self->chat) {
|
||||
if (self->chat) {
|
||||
linphone_chat_message_unref(self->chat);
|
||||
linphone_chat_message_set_user_data(self->chat, NULL);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(self->chat), NULL);
|
||||
}
|
||||
self->chat = message;
|
||||
messageImageView.image = nil;
|
||||
[self disconnectFromFileDelegate];
|
||||
for (FileTransferDelegate *aftd in [[LinphoneManager instance] fileTransferDelegates]) {
|
||||
if (message &&
|
||||
linphone_chat_message_get_storage_id(aftd.message) == linphone_chat_message_get_storage_id(message)) {
|
||||
LOGI(@"Chat message [%p] with file transfer delegate [%p], connecting to it!", message,
|
||||
linphone_chat_message_get_user_data(message));
|
||||
[self connectToFileDelegate:aftd];
|
||||
break;
|
||||
if (self->chat) {
|
||||
linphone_chat_message_ref(self->chat);
|
||||
linphone_chat_message_set_user_data(self->chat, (void *)CFBridgingRetain(self));
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(self->chat),
|
||||
message_status);
|
||||
|
||||
const LinphoneContent *c = linphone_chat_message_get_file_transfer_information(message);
|
||||
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);
|
||||
[self connectToFileDelegate:aftd];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[self update];
|
||||
|
|
@ -353,7 +375,6 @@ static UIFont *CELL_FONT = nil;
|
|||
- (IBAction)onDownloadClick:(id)event {
|
||||
if (ftd.message == nil) {
|
||||
ftd = [[FileTransferDelegate alloc] init];
|
||||
[[[LinphoneManager instance] fileTransferDelegates] addObject:ftd];
|
||||
[self connectToFileDelegate:ftd];
|
||||
[ftd download:chat];
|
||||
_cancelButton.hidden = NO;
|
||||
|
|
@ -423,6 +444,11 @@ static UIFont *CELL_FONT = nil;
|
|||
}
|
||||
}
|
||||
}
|
||||
#pragma mark - State changed handler
|
||||
static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
|
||||
UIChatRoomCell *thiz = (__bridge UIChatRoomCell *)linphone_chat_message_get_user_data(msg);
|
||||
[thiz update];
|
||||
}
|
||||
|
||||
#pragma mark - LinphoneFileTransfer Notifications Handling
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
+ (FileTransferDelegate *)messageDelegate:(LinphoneChatMessage *)message {
|
||||
for (FileTransferDelegate *ftd in [[LinphoneManager instance] fileTransferDelegates]) {
|
||||
if (ftd.message == message) {
|
||||
return ftd;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, const LinphoneContent *content,
|
||||
const LinphoneBuffer *buffer) {
|
||||
FileTransferDelegate *thiz = (__bridge FileTransferDelegate *)linphone_chat_message_get_user_data(message);
|
||||
FileTransferDelegate *thiz = [FileTransferDelegate messageDelegate:message];
|
||||
size_t size = linphone_buffer_get_size(buffer);
|
||||
|
||||
if (!thiz.data) {
|
||||
|
|
@ -35,7 +44,7 @@ static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, con
|
|||
// we're finished, save the image and update the message
|
||||
UIImage *image = [UIImage imageWithData:thiz.data];
|
||||
|
||||
|
||||
CFBridgingRetain(thiz);
|
||||
[[[LinphoneManager instance] fileTransferDelegates] removeObject:thiz];
|
||||
|
||||
[[LinphoneManager instance]
|
||||
|
|
@ -59,6 +68,7 @@ static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, con
|
|||
forKey:@"localimage"
|
||||
inMessage:message];
|
||||
}
|
||||
linphone_chat_message_unref(thiz.message);
|
||||
thiz.message = NULL;
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:kLinphoneFileTransferRecvUpdate
|
||||
|
|
@ -88,7 +98,7 @@ static void linphone_iphone_file_transfer_recv(LinphoneChatMessage *message, con
|
|||
|
||||
static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *message, const LinphoneContent *content,
|
||||
size_t offset, size_t size) {
|
||||
FileTransferDelegate *thiz = (__bridge FileTransferDelegate *)linphone_chat_message_get_user_data(message);
|
||||
FileTransferDelegate *thiz = [FileTransferDelegate messageDelegate:message];
|
||||
size_t total = thiz.data.length;
|
||||
if (thiz.data) {
|
||||
size_t remaining = total - offset;
|
||||
|
|
@ -97,16 +107,26 @@ static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *m
|
|||
@"state" : @(linphone_chat_message_get_state(message)),
|
||||
@"progress" : @(offset * 1.f / total),
|
||||
}];
|
||||
LOGD(@"Transfer of %s (%d bytes): already sent %ld, remaining %ld", linphone_content_get_name(content), total,
|
||||
offset, remaining);
|
||||
LOGD(@"Transfer of %s (%d bytes): already sent %ld (%f%%), remaining %ld", linphone_content_get_name(content),
|
||||
total, offset, offset * 100.f / total, remaining);
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneFileTransferSendUpdate
|
||||
object:thiz
|
||||
userInfo:dict];
|
||||
|
||||
LinphoneBuffer *buffer = NULL;
|
||||
@try {
|
||||
return linphone_buffer_new_from_data([thiz.data subdataWithRange:NSMakeRange(offset, size)].bytes, size);
|
||||
buffer = linphone_buffer_new_from_data([thiz.data subdataWithRange:NSMakeRange(offset, size)].bytes, size);
|
||||
} @catch (NSException *exception) {
|
||||
LOGE(@"Exception: %@", exception);
|
||||
}
|
||||
|
||||
// this is the last time we will be notified, so destroy ourselve
|
||||
if (remaining <= size) {
|
||||
linphone_chat_message_unref(thiz.message);
|
||||
thiz.message = NULL;
|
||||
[thiz stopAndDestroy];
|
||||
}
|
||||
return buffer;
|
||||
} else {
|
||||
LOGE(@"Transfer of %s (%d bytes): %d Error - no upload data in progress!", linphone_content_get_name(content),
|
||||
total, offset);
|
||||
|
|
@ -115,28 +135,9 @@ static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *m
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState state) {
|
||||
FileTransferDelegate *thiz = (__bridge FileTransferDelegate *)linphone_chat_message_get_user_data(msg);
|
||||
|
||||
NSString *notification =
|
||||
linphone_chat_message_is_outgoing(msg) ? kLinphoneFileTransferSendUpdate : kLinphoneFileTransferRecvUpdate;
|
||||
|
||||
const char *text = (linphone_chat_message_get_file_transfer_information(msg) != NULL)
|
||||
? "photo transfer"
|
||||
: linphone_chat_message_get_text(msg);
|
||||
LOGI(@"Delivery status for [%s] is [%s]", text, linphone_chat_message_state_to_string(state));
|
||||
|
||||
NSDictionary *dict = @{ @"state" : @(state), @"progress" : @0.f };
|
||||
if (state == LinphoneChatMessageStateFileTransferDone || state == LinphoneChatMessageStateFileTransferError) {
|
||||
thiz.message = NULL;
|
||||
}
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:notification object:thiz userInfo:dict];
|
||||
if (linphone_chat_message_is_outgoing(msg)) {
|
||||
[thiz stopAndDestroy];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)upload:(UIImage *)image withURL:(NSURL *)url forChatRoom:(LinphoneChatRoom *)chatRoom {
|
||||
[[[LinphoneManager instance] fileTransferDelegates] addObject:self];
|
||||
|
||||
LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_lc(chatRoom));
|
||||
_data = [NSMutableData dataWithData:UIImageJPEGRepresentation(image, 1.0)];
|
||||
linphone_content_set_type(content, "image");
|
||||
|
|
@ -146,38 +147,36 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
|
|||
[NSDate timeIntervalSinceReferenceDate]] UTF8String]);
|
||||
linphone_content_set_size(content, [_data length]);
|
||||
|
||||
CFTypeRef myself = (__bridge CFTypeRef)self;
|
||||
_message = linphone_chat_room_create_file_transfer_message(chatRoom, content);
|
||||
linphone_chat_message_ref(_message);
|
||||
linphone_chat_message_set_user_data(_message, (void *)CFRetain(myself));
|
||||
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(_message),
|
||||
linphone_iphone_file_transfer_send);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), message_status);
|
||||
|
||||
if (url) {
|
||||
// internal url is saved in the appdata for display and later save
|
||||
[LinphoneManager setValueInMessageAppData:[url absoluteString] forKey:@"localimage" inMessage:_message];
|
||||
}
|
||||
|
||||
LOGI(@"%p Uploading content in %p", self, _message);
|
||||
|
||||
linphone_chat_room_send_chat_message(chatRoom, _message);
|
||||
}
|
||||
|
||||
- (BOOL)download:(LinphoneChatMessage *)message {
|
||||
[[[LinphoneManager instance] fileTransferDelegates] addObject:self];
|
||||
|
||||
_message = message;
|
||||
// we need to keep a ref on the message to continue downloading even if user quit a chatroom which destroy all chat
|
||||
// messages
|
||||
linphone_chat_message_ref(_message);
|
||||
const char *url = linphone_chat_message_get_external_body_url(_message);
|
||||
LOGI(@"Content to download: %s", url);
|
||||
LOGI(@"%p Downloading content in %p from %s", self, message, url);
|
||||
|
||||
if (url == nil)
|
||||
return FALSE;
|
||||
|
||||
linphone_chat_message_set_user_data(_message, (void *)CFBridgingRetain(self));
|
||||
|
||||
linphone_chat_message_cbs_set_file_transfer_recv(linphone_chat_message_get_callbacks(_message),
|
||||
linphone_iphone_file_transfer_recv);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), message_status);
|
||||
|
||||
linphone_chat_message_download_file(_message);
|
||||
|
||||
|
|
@ -187,18 +186,17 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
|
|||
- (void)stopAndDestroy {
|
||||
[[[LinphoneManager instance] fileTransferDelegates] removeObject:self];
|
||||
if (_message != NULL) {
|
||||
linphone_chat_message_set_user_data(_message, NULL);
|
||||
|
||||
LOGI(@"%p Cancelling transferm from %p", self, _message);
|
||||
linphone_chat_message_cbs_set_file_transfer_progress_indication(linphone_chat_message_get_callbacks(_message),
|
||||
NULL);
|
||||
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(_message), NULL);
|
||||
linphone_chat_message_cbs_set_file_transfer_recv(linphone_chat_message_get_callbacks(_message), NULL);
|
||||
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), NULL);
|
||||
linphone_chat_message_cancel_file_transfer(_message);
|
||||
linphone_chat_message_unref(_message);
|
||||
}
|
||||
_message = nil;
|
||||
_data = nil;
|
||||
LOGI(@"%p Destroying", self);
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
if ([tester tryFindingTappableViewWithAccessibilityLabel:@"Back" error:nil]) {
|
||||
[self goBackFromChat];
|
||||
}
|
||||
ASSERT_EQ([LinphoneManager instance].fileTransferDelegates.count, 0)
|
||||
}
|
||||
|
||||
#pragma mark - tools
|
||||
|
|
@ -163,11 +164,11 @@
|
|||
return tv;
|
||||
}
|
||||
|
||||
- (void)uploadImage {
|
||||
NSString *user = @"testios";
|
||||
|
||||
[self startChatWith:user];
|
||||
- (void)uploadImageWithQuality:(NSString *)quality {
|
||||
UITableView *tv = [self findTableView:@"Chat list"];
|
||||
|
||||
long messagesCount = [tv numberOfRowsInSection:0];
|
||||
long delegatesCount = [[[LinphoneManager instance] fileTransferDelegates] count];
|
||||
[tester tapViewWithAccessibilityLabel:@"Send picture"];
|
||||
[tester tapViewWithAccessibilityLabel:@"Photo library"];
|
||||
// if popup "Linphone would access your photo" pops up, click OK.
|
||||
|
|
@ -177,32 +178,33 @@
|
|||
#endif
|
||||
}
|
||||
|
||||
[tester choosePhotoInAlbum:@"Camera Roll" atRow:1 column:1];
|
||||
// select another photo if already uploading one
|
||||
[tester choosePhotoInAlbum:@"Camera Roll" atRow:1 + delegatesCount column:1];
|
||||
|
||||
// wait for the quality popup to show up
|
||||
[tester waitForTimeInterval:1];
|
||||
|
||||
UIAccessibilityElement *element =
|
||||
[[UIApplication sharedApplication] accessibilityElementMatchingBlock:^BOOL(UIAccessibilityElement *element) {
|
||||
return [element.accessibilityLabel containsString:@"Minimum ("];
|
||||
return [element.accessibilityLabel containsString:quality];
|
||||
}];
|
||||
[tester tapViewWithAccessibilityLabel:element.accessibilityLabel];
|
||||
|
||||
UITableView *tv = [self findTableView:@"Chat list"];
|
||||
ASSERT_EQ([tv numberOfRowsInSection:0], 1);
|
||||
ASSERT_EQ([[[LinphoneManager instance] fileTransferDelegates] count], 1);
|
||||
ASSERT_EQ([tv numberOfRowsInSection:0], messagesCount + 1);
|
||||
ASSERT_EQ([[[LinphoneManager instance] fileTransferDelegates] count], delegatesCount + 1);
|
||||
}
|
||||
|
||||
- (void)testUploadImage {
|
||||
NSString *user = @"testios";
|
||||
NSString *myself = @"testios";
|
||||
[self startChatWith:myself];
|
||||
|
||||
ASSERT_EQ([[LinphoneManager instance] fileTransferDelegates].count, 0);
|
||||
[self uploadImage];
|
||||
[self uploadImageWithQuality:@"Minimum"];
|
||||
ASSERT_EQ([[LinphoneManager instance] fileTransferDelegates].count, 1);
|
||||
[self goBackFromChat];
|
||||
|
||||
// if we go back to the same chatroom, the message should be still there
|
||||
[self startChatWith:user];
|
||||
[self startChatWith:myself];
|
||||
UITableView *tv = [self findTableView:@"Chat list"];
|
||||
ASSERT_EQ([tv numberOfRowsInSection:0], 1);
|
||||
|
||||
|
|
@ -219,7 +221,9 @@
|
|||
}
|
||||
|
||||
- (void)testCancelUploadImage {
|
||||
[self uploadImage];
|
||||
NSString *myself = @"testios";
|
||||
[self startChatWith:myself];
|
||||
[self uploadImageWithQuality:@"Minimum"];
|
||||
[tester tapViewWithAccessibilityLabel:@"Cancel transfer"];
|
||||
if ([[[LinphoneManager instance] fileTransferDelegates] count] != 0) {
|
||||
[[UIApplication sharedApplication] writeScreenshotForLine:__LINE__ inFile:@__FILE__ description:nil error:NULL];
|
||||
|
|
@ -228,8 +232,29 @@
|
|||
ASSERT_EQ([[[LinphoneManager instance] fileTransferDelegates] count], 0);
|
||||
}
|
||||
|
||||
- (void)test3UploadsSimultanously {
|
||||
NSString *myself = @"testios";
|
||||
[self startChatWith:myself];
|
||||
// use Maximum quality to be sure that first transfer is not terminated when the third begins
|
||||
[self uploadImageWithQuality:@"Maximum"];
|
||||
[self uploadImageWithQuality:@"Maximum"];
|
||||
[self uploadImageWithQuality:@"Minimum"];
|
||||
UITableView *tv = [self findTableView:@"Chat list"];
|
||||
ASSERT_EQ([[LinphoneManager instance] fileTransferDelegates].count, 3);
|
||||
// wait for ALL uploads to terminate...
|
||||
for (int i = 0; i < 45; i++) {
|
||||
[tester waitForTimeInterval:1.f];
|
||||
if ([tv numberOfRowsInSection:0] == 6)
|
||||
break;
|
||||
}
|
||||
ASSERT_EQ([[LinphoneManager instance] fileTransferDelegates].count, 0);
|
||||
ASSERT_EQ([tv numberOfRowsInSection:0], 6);
|
||||
}
|
||||
|
||||
- (void)downloadImage {
|
||||
[self uploadImage];
|
||||
NSString *myself = @"testios";
|
||||
[self startChatWith:myself];
|
||||
[self uploadImageWithQuality:@"Minimum"];
|
||||
// wait for the upload to terminate...
|
||||
for (int i = 0; i < 15; i++) {
|
||||
[tester waitForTimeInterval:1.f];
|
||||
|
|
@ -242,6 +267,26 @@
|
|||
ASSERT_EQ([[[LinphoneManager instance] fileTransferDelegates] count], 1);
|
||||
}
|
||||
|
||||
- (void)test3DownloadsSimultanously {
|
||||
[self startChatWith:[self me]];
|
||||
[self uploadImageWithQuality:@"Maximum"];
|
||||
[self uploadImageWithQuality:@"Average"];
|
||||
[self uploadImageWithQuality:@"Minimum"];
|
||||
UITableView *tv = [self findTableView:@"Chat list"];
|
||||
// wait for ALL uploads to terminate...
|
||||
for (int i = 0; i < 45; i++) {
|
||||
[tester waitForTimeInterval:1.f];
|
||||
if ([tv numberOfRowsInSection:0] == 6)
|
||||
break;
|
||||
}
|
||||
ASSERT_EQ([[LinphoneManager instance] fileTransferDelegates].count, 0);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
[tester waitForViewWithAccessibilityLabel:@"Download"];
|
||||
[tester tapViewWithAccessibilityLabel:@"Download"];
|
||||
[tester waitForTimeInterval:.5f]; // just wait a few secs to start download
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testDownloadImage {
|
||||
[self downloadImage];
|
||||
[tester waitForAbsenceOfViewWithAccessibilityLabel:@"Cancel transfer"];
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash -x
|
||||
#!/bin/bash
|
||||
|
||||
# Install underscore-cli for hacking
|
||||
if ! which underscore &> /dev/null; then
|
||||
|
|
|
|||
5
main.m
5
main.m
|
|
@ -36,7 +36,6 @@ int main(int argc, char *argv[]) {
|
|||
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
|
||||
#endif
|
||||
@autoreleasepool {
|
||||
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([LinphoneAppDelegate class]));
|
||||
return retVal;
|
||||
}
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([LinphoneAppDelegate class]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 2f795533d68784ae58abd6a43b24281d33c5730d
|
||||
Subproject commit cfd87c55acee96699ce8306a3734b477fee3a00a
|
||||
Loading…
Add table
Reference in a new issue