First version of internal storage use for iOS

This commit is contained in:
Guillaume BIENKOWSKI 2014-05-19 16:57:52 +02:00
parent 9bd9152959
commit 4a136403b4
20 changed files with 376 additions and 765 deletions

View file

@ -19,27 +19,28 @@
#import <UIKit/UIKit.h>
#import "ChatModel.h"
#include "linphone/linphonecore.h"
@protocol ChatRoomDelegate <NSObject>
- (BOOL)chatRoomStartImageDownload:(NSURL*)url userInfo:(id)userInfo;
- (BOOL)chatRoomStartImageUpload:(UIImage*)image url:(NSURL*)url;
- (void)resendChat:(NSString*)message;
- (void)resendChat:(NSString*)message withExternalUrl:(NSString*)url;
@end
@interface ChatRoomTableViewController : UITableViewController {
@private
NSMutableArray *data;
LinphoneChatRoom* chatRoom;
MSList *messageList;
}
@property (nonatomic, copy) NSString *remoteAddress;
@property (nonatomic, retain) id<ChatRoomDelegate> chatRoomDelegate;
- (void)addChatEntry:(ChatModel*)chat;
- (void)addChatEntry:(LinphoneChatMessage*)chat;
- (void)scrollToBottom:(BOOL)animated;
- (void)scrollToLastUnread:(BOOL)animated;
- (void)updateChatEntry:(ChatModel*)chat;
- (void)updateChatEntry:(LinphoneChatMessage*)chat;
- (void)setChatRoom:(LinphoneChatRoom*)room;
@end

View file

@ -27,14 +27,13 @@
@implementation ChatRoomTableViewController
@synthesize remoteAddress;
@synthesize chatRoomDelegate;
#pragma mark - Lifecycle Functions
- (void)dealloc {
[remoteAddress release];
[chatRoomDelegate release];
[self clearMessageList];
[super dealloc];
}
@ -44,82 +43,98 @@
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[TUNinePatchCache flushCache]; // Clear cache
if(data != nil) {
[data removeAllObjects];
[data release];
data = nil;
}
[self clearMessageList];
chatRoom = NULL;
}
- (void)viewWillAppear:(BOOL)animated {
[self loadData];
[self reloadData];
}
#pragma mark -
- (void)loadData {
if(data != nil) {
[data removeAllObjects];
[data release];
- (void)clearMessageList {
if (messageList){
ms_list_free_with_data(messageList, (void(*)(void*))linphone_chat_message_unref);
messageList = nil;
}
data = [[ChatModel listMessages:remoteAddress] retain];
[[self tableView] reloadData];
}
- (void)updateData {
if( !chatRoom ) return;
[self clearMessageList];
self->messageList = linphone_chat_room_get_history(chatRoom, 0);
}
- (void)reloadData {
[self updateData];
[self.tableView reloadData];
[self scrollToLastUnread:false];
}
- (void)addChatEntry:(ChatModel*)chat {
if(data == nil) {
[LinphoneLogger logc:LinphoneLoggerWarning format:"Cannot add entry: null data"];
return;
}
- (void)addChatEntry:(LinphoneChatMessage*)chat {
messageList = ms_list_append(messageList, chat);
int pos = ms_list_size(messageList) - 1;
[self.tableView beginUpdates];
int pos = [data count];
[data insertObject:chat atIndex:pos];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:pos inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:pos inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
}
- (void)updateChatEntry:(ChatModel*)chat {
if(data == nil) {
[LinphoneLogger logc:LinphoneLoggerWarning format:"Cannot update entry: null data"];
return;
}
NSInteger index = [data indexOfObject:chat];
- (void)updateChatEntry:(LinphoneChatMessage*)chat {
NSInteger index = ms_list_index(self->messageList, chat);
if (index<0) {
[LinphoneLogger logc:LinphoneLoggerWarning format:"chat entries diesn not exixt"];
[LinphoneLogger logc:LinphoneLoggerWarning format:"chat entry doesn't exist"];
return;
}
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:index inSection:0]] withRowAnimation:FALSE];; //just reload
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:index inSection:0]] withRowAnimation:FALSE]; //just reload
return;
}
- (void)scrollToBottom:(BOOL)animated {
[self.tableView reloadData];
if( [data count] ){
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:([data count] - 1) inSection:0]
int count = ms_list_size(messageList);
if( count ){
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(count - 1) inSection:0]
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}
}
- (void)debugMessages {
if( !messageList ){
NSLog(@"No data to debug");
return;
}
MSList*item = self->messageList;
int count = 0;
while (item) {
LinphoneChatMessage* msg = (LinphoneChatMessage*)item->data;
NSLog(@"Message %d: %s", count++, linphone_chat_message_get_text(msg));
item = item->next;
}
}
- (void)scrollToLastUnread:(BOOL)animated {
if(data == nil) {
[LinphoneLogger logc:LinphoneLoggerWarning format:"Cannot add entry: null data"];
if(messageList == nil || chatRoom == nil) {
return;
}
int index = -1;
int count = ms_list_size(messageList);
// Find first unread & set all entry read
for(int i = 0; i <[data count]; ++i) {
ChatModel *chat = [data objectAtIndex:i];
if([[chat read] intValue] == 0) {
[chat setRead:[NSNumber numberWithInt:1]];
for(int i = 0; i <count; ++i) {
int read = linphone_chat_message_is_read(ms_list_nth_data(messageList, i));
if(read == 0) {
if(index == -1)
index = i;
}
}
if(index == -1) {
index = [data count] - 1;
index = count - 1;
}
linphone_chat_room_mark_as_read(chatRoom);
// Scroll to unread
if(index >= 0) {
@ -132,15 +147,11 @@
#pragma mark - Property Functions
- (void)setRemoteAddress:(NSString *)aremoteAddress {
if(remoteAddress != nil) {
[remoteAddress release];
}
self->remoteAddress = [aremoteAddress copy];
[self loadData];
- (void)setChatRoom:(LinphoneChatRoom*)room {
chatRoom = room;
[self reloadData];
}
#pragma mark - UITableViewDataSource Functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
@ -148,7 +159,7 @@
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [data count];
return ms_list_size(self->messageList);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@ -157,8 +168,9 @@
if (cell == nil) {
cell = [[[UIChatRoomCell alloc] initWithIdentifier:kCellId] autorelease];
}
[cell setChat:[data objectAtIndex:[indexPath row]]];
LinphoneChatMessage* chat = ms_list_nth_data(self->messageList, [indexPath row]);
[cell setChatMessage:chat];
[cell setChatRoomDelegate:chatRoomDelegate];
return cell;
}
@ -169,11 +181,16 @@
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if(editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
ChatModel *chat = [data objectAtIndex:[indexPath row]];
[data removeObjectAtIndex:[indexPath row]];
[chat delete];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
LinphoneChatMessage *chat = ms_list_nth_data(self->messageList, [indexPath row]);
if( chat ){
linphone_chat_room_delete_message(chatRoom, chat);
messageList = ms_list_remove(messageList, chat);
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
}
[tableView endUpdates];
}
}
@ -186,8 +203,8 @@
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
ChatModel *chat = [data objectAtIndex:[indexPath row]];
return [UIChatRoomCell height:chat width:[self.view frame].size.width];
LinphoneChatMessage* message = ms_list_nth_data(self->messageList, [indexPath row]);
return [UIChatRoomCell height:message width:[self.view frame].size.width];
}
@end

View file

@ -23,7 +23,6 @@
#import "UICompositeViewController.h"
#import "ChatRoomTableViewController.h"
#import "HPGrowingTextView.h"
#import "ChatModel.h"
#import "ImagePickerViewController.h"
#import "ImageSharing.h"
#import "OrderedDictionary.h"
@ -53,7 +52,6 @@
@property (retain, nonatomic) IBOutlet UILabel *composeLabel;
@property (retain, nonatomic) IBOutlet UIView *composeIndicatorView;
@property (nonatomic, copy) NSString *remoteAddress;
@property (nonatomic, retain) IBOutlet UIButton* pictureButton;
@property (nonatomic, retain) IBOutlet UIButton* cancelTransferButton;
@property (nonatomic, retain) IBOutlet UIProgressView* imageTransferProgressBar;
@ -68,4 +66,6 @@
- (IBAction)onTransferCancelClick:(id)event;
- (IBAction)onListTap:(id)sender;
- (void)setChatRoom:(LinphoneChatRoom*)room;
@end

View file

@ -32,7 +32,6 @@
@synthesize sendButton;
@synthesize messageField;
@synthesize editButton;
@synthesize remoteAddress;
@synthesize addressLabel;
@synthesize composeLabel;
@synthesize composeIndicatorView;
@ -73,7 +72,6 @@
[messageField release];
[sendButton release];
[editButton release];
[remoteAddress release];
[addressLabel release];
[avatarImage release];
[headerView release];
@ -245,49 +243,32 @@ static UICompositeViewDescription *compositeDescription = nil;
#pragma mark -
- (void)setRemoteAddress:(NSString*)aRemoteAddress {
if(remoteAddress != nil) {
[remoteAddress release];
}
if ([aRemoteAddress hasPrefix:@"sip:"] || [aRemoteAddress hasPrefix:@"sips:"]) {
remoteAddress = [aRemoteAddress copy];
} else {
char normalizedUserName[256];
LinphoneCore *lc = [LinphoneManager getLc];
LinphoneProxyConfig* proxyCfg;
linphone_core_get_default_proxy(lc,&proxyCfg);
LinphoneAddress* linphoneAddress = linphone_address_new(linphone_core_get_identity(lc));
linphone_proxy_config_normalize_number(proxyCfg, [aRemoteAddress cStringUsingEncoding:[NSString defaultCStringEncoding]], normalizedUserName, sizeof(normalizedUserName));
linphone_address_set_username(linphoneAddress, normalizedUserName);
remoteAddress = [[NSString stringWithUTF8String:linphone_address_as_string_uri_only(linphoneAddress)] copy];
linphone_address_destroy(linphoneAddress);
}
- (void)setChatRoom:(LinphoneChatRoom *)room {
self->chatRoom = room;
[messageField setText:@""];
chatRoom = linphone_core_get_or_create_chat_room([LinphoneManager getLc], [remoteAddress cStringUsingEncoding:[NSString defaultCStringEncoding]]);
[tableController setChatRoom:room];
[self update];
[tableController setRemoteAddress: remoteAddress];
[ChatModel readConversation:remoteAddress];
linphone_chat_room_mark_as_read(chatRoom);
[self setComposingVisible:linphone_chat_room_is_remote_composing(chatRoom) withDelay:0];
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextReceived object:self];
}
- (void)applicationWillEnterForeground:(NSNotification*)notif {
if(remoteAddress != nil) {
[ChatModel readConversation:remoteAddress];
if(chatRoom != nil) {
linphone_chat_room_mark_as_read(chatRoom);
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextReceived object:self];
}
}
- (void)update {
if(remoteAddress == NULL) {
if(chatRoom == NULL) {
[LinphoneLogger logc:LinphoneLoggerWarning format:"Cannot update chat room header: null contact"];
return;
}
NSString *displayName = nil;
UIImage *image = nil;
LinphoneAddress* linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [remoteAddress UTF8String]);
const LinphoneAddress* linphoneAddress = linphone_chat_room_get_peer_address(chatRoom);
if (linphoneAddress == NULL) {
[[PhoneMainView instance] popCurrentView];
UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Invalid SIP address",nil)
@ -308,8 +289,6 @@ static UICompositeViewDescription *compositeDescription = nil;
displayName = [FastAddressBook getContactDisplayName:acontact];
image = [FastAddressBook getContactImage:acontact thumbnail:true];
}
[remoteAddress release];
remoteAddress = [normalizedSipAddress retain];
// Display name
if(displayName == nil) {
@ -323,61 +302,33 @@ static UICompositeViewDescription *compositeDescription = nil;
}
[avatarImage setImage:image];
linphone_address_destroy(linphoneAddress);
}
static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud) {
ChatRoomViewController* thiz = (ChatRoomViewController*)ud;
ChatModel *chat = (ChatModel *)linphone_chat_message_get_user_data(msg);
const char*text = linphone_chat_message_get_text(msg);
[LinphoneLogger log:LinphoneLoggerLog
format:@"Delivery status for [%@] is [%s]",(chat.message?chat.message:@""),linphone_chat_message_state_to_string(state)];
[chat setState:[NSNumber numberWithInt:state]];
[chat update];
[thiz.tableController updateChatEntry:chat];
if (state != LinphoneChatMessageStateInProgress) {
linphone_chat_message_set_user_data(msg, NULL);
[chat release]; // no longuer need to keep reference
}
format:@"Delivery status for [%s] is [%s]",text,linphone_chat_message_state_to_string(state)];
[thiz.tableController updateChatEntry:msg];
}
- (BOOL)sendMessage:(NSString *)message withExterlBodyUrl:(NSURL*)externalUrl withInternalUrl:(NSURL*)internalUrl {
- (BOOL)sendMessage:(NSString *)message withExterlBodyUrl:(NSURL*)externalUrl {
if(![LinphoneManager isLcReady]) {
[LinphoneLogger logc:LinphoneLoggerWarning format:"Cannot send message: Linphone core not ready"];
return FALSE;
}
if(remoteAddress == nil) {
[LinphoneLogger logc:LinphoneLoggerWarning format:"Cannot send message: Null remoteAddress"];
if(chatRoom == NULL) {
[LinphoneLogger logc:LinphoneLoggerWarning format:"Cannot send message: No chatroom"];
return FALSE;
}
if(chatRoom == NULL) {
chatRoom = linphone_core_create_chat_room([LinphoneManager getLc], [remoteAddress UTF8String]);
}
// Save message in database
ChatModel *chat = [[ChatModel alloc] init];
[chat setRemoteContact:remoteAddress];
[chat setLocalContact:@""];
if(internalUrl == nil) {
[chat setMessage:message];
} else {
[chat setMessage:[internalUrl absoluteString]];
}
[chat setDirection:[NSNumber numberWithInt:0]];
[chat setTime:[NSDate date]];
[chat setRead:[NSNumber numberWithInt:1]];
[chat setState:[NSNumber numberWithInt:1]]; //INPROGRESS
[chat create];
[tableController addChatEntry:chat];
[tableController scrollToBottom:true];
[chat release];
LinphoneChatMessage* msg = linphone_chat_room_create_message(chatRoom, [message UTF8String]);
linphone_chat_message_set_user_data(msg, [chat retain]);
if(externalUrl) {
linphone_chat_message_set_external_body_url(msg, [[externalUrl absoluteString] UTF8String]);
}
[tableController addChatEntry:linphone_chat_message_ref(msg)];
linphone_chat_room_send_message2(chatRoom, msg, message_status, self);
[tableController scrollToBottom:true];
return TRUE;
}
@ -476,29 +427,31 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
}
- (void)textReceivedEvent:(NSNotification *)notif {
//LinphoneChatRoom *room = [[[notif userInfo] objectForKey:@"room"] pointerValue];
//NSString *message = [[notif userInfo] objectForKey:@"message"];
LinphoneAddress *from = [[[notif userInfo] objectForKey:@"from"] pointerValue];
ChatModel *chat = [[notif userInfo] objectForKey:@"chat"];
LinphoneAddress * from = [[[notif userInfo] objectForKey:@"from_address"] pointerValue];
LinphoneChatRoom* room = [[notif.userInfo objectForKey:@"room"] pointerValue];
LinphoneChatMessage* chat = [[notif.userInfo objectForKey:@"message"] pointerValue];
if(from == NULL || chat == NULL) {
return;
}
char *fromStr = linphone_address_as_string_uri_only(from);
if(fromStr != NULL) {
if([[NSString stringWithUTF8String:fromStr]
caseInsensitiveCompare:remoteAddress] == NSOrderedSame) {
const LinphoneAddress* cr_from = linphone_chat_room_get_peer_address(chatRoom);
char* cr_from_string = linphone_address_as_string_uri_only(cr_from);
if(fromStr && cr_from_string ) {
if(strcasecmp(cr_from_string, fromStr) == 0) {
if (![[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]
|| [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
[chat setRead:[NSNumber numberWithInt:1]];
[chat update];
linphone_chat_room_mark_as_read(room);
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextReceived object:self];
}
[tableController addChatEntry:chat];
[tableController scrollToLastUnread:TRUE];
}
ms_free(fromStr);
}
ms_free(fromStr);
ms_free(cr_from_string);
}
- (void)textComposeEvent:(NSNotification*)notif {
@ -577,7 +530,7 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
}
- (IBAction)onSendClick:(id)event {
if([self sendMessage:[messageField text] withExterlBodyUrl:nil withInternalUrl:nil]) {
if([self sendMessage:[messageField text] withExterlBodyUrl:nil]) {
scrollOnGrowingEnabled = FALSE;
[messageField setText:@""];
scrollOnGrowingEnabled = TRUE;
@ -673,8 +626,8 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
return FALSE;
}
- (void)resendChat:(NSString *)message {
[self sendMessage:message withExterlBodyUrl:nil withInternalUrl:nil];
- (void)resendChat:(NSString *)message withExternalUrl:(NSString *)url {
[self sendMessage:message withExterlBodyUrl:[NSURL URLWithString:url]];
}
#pragma mark ImageSharingDelegate
@ -717,9 +670,7 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
}
- (void)imageSharingUploadDone:(ImageSharing*)aimageSharing url:(NSURL*)url{
NSURL *imageURL = [aimageSharing userInfo];
[self sendMessage:nil withExterlBodyUrl:url withInternalUrl:imageURL];
[self sendMessage:nil withExterlBodyUrl:url];
[messageView setHidden:FALSE];
[transferView setHidden:TRUE];
@ -730,7 +681,7 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
[messageView setHidden:FALSE];
[transferView setHidden:TRUE];
ChatModel *chat = (ChatModel *)[imageSharing userInfo];
__block LinphoneChatMessage *chat = (LinphoneChatMessage *)[(NSValue*)[imageSharing userInfo] pointerValue];
[[LinphoneManager instance].photoLibrary writeImageToSavedPhotosAlbum:image.CGImage
orientation:(ALAssetOrientation)[image imageOrientation]
completionBlock:^(NSURL *assetURL, NSError *error){
@ -747,8 +698,8 @@ static void message_status(LinphoneChatMessage* msg,LinphoneChatMessageState sta
return;
}
[LinphoneLogger log:LinphoneLoggerLog format:@"Image saved to [%@]", [assetURL absoluteString]];
[chat setMessage:[assetURL absoluteString]];
[chat update];
linphone_chat_message_set_external_body_url(chat, [[assetURL absoluteString] UTF8String]);
linphone_chat_room_update_url(chatRoom, chat);
[tableController updateChatEntry:chat];
}];
imageSharing = nil;

View file

@ -18,12 +18,10 @@
*/
#import <UIKit/UIKit.h>
#include "linphone/linphonecore.h"
@interface ChatTableViewController : UITableViewController {
@private
NSMutableArray *data;
}
- (void)loadData;
@end

View file

@ -26,14 +26,15 @@
#import "UILinphone.h"
#import "Utils.h"
@implementation ChatTableViewController
@implementation ChatTableViewController {
@private
MSList* data;
}
#pragma mark - Lifecycle Functions
- (void)dealloc {
if(data != nil)
[data release];
[super dealloc];
}
@ -49,9 +50,7 @@
#pragma mark -
- (void)loadData {
if(data != nil)
[data release];
data = [[ChatModel listConversations] retain];
data = linphone_core_get_chat_rooms([LinphoneManager getLc]);
[[self tableView] reloadData];
}
@ -62,7 +61,7 @@
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [data count];
return ms_list_size(data);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@ -78,7 +77,7 @@
[selectedBackgroundView setBackgroundColor:LINPHONE_TABLE_CELL_BACKGROUND_COLOR];
}
[cell setChat:[data objectAtIndex:[indexPath row]]];
[cell setChatRoom:(LinphoneChatRoom*)ms_list_nth_data(data, [indexPath row])];
return cell;
}
@ -88,12 +87,12 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
ChatModel *chat = [data objectAtIndex:[indexPath row]];
LinphoneChatRoom *chatRoom = (LinphoneChatRoom*)ms_list_nth_data(data, [indexPath row]);
// Go to ChatRoom view
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
if(controller != nil) {
[controller setRemoteAddress:[chat remoteContact]];
[controller setChatRoom:chatRoom];
}
}
@ -108,9 +107,12 @@
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if(editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
ChatModel *chat = [data objectAtIndex:[indexPath row]];
[ChatModel removeConversation:[chat remoteContact]];
[data removeObjectAtIndex:[indexPath row]];
LinphoneChatRoom *chatRoom = (LinphoneChatRoom*)ms_list_nth_data(data, [indexPath row]);
linphone_chat_room_delete_history(chatRoom);
linphone_chat_room_destroy(chatRoom);
data = linphone_core_get_chat_rooms([LinphoneManager getLc]);
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextReceived object:self];

View file

@ -20,7 +20,6 @@
#import "ChatViewController.h"
#import "PhoneMainView.h"
#import "ChatModel.h"
@implementation ChatViewController
@synthesize tableController;
@ -113,7 +112,8 @@ static UICompositeViewDescription *compositeDescription = nil;
//Push ChatRoom
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
if(controller != nil) {
[controller setRemoteAddress:[addressField text]];
LinphoneChatRoom* room = linphone_core_get_or_create_chat_room([LinphoneManager getLc], [addressField.text UTF8String]);
[controller setChatRoom:room];
}
addressField.text = @"";

View file

@ -651,7 +651,8 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {ContactSe
[[PhoneMainView instance] popToView:[ChatViewController compositeViewDescription]]; // Got to Chat and push ChatRoom
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
if(controller != nil) {
[controller setRemoteAddress:dest];
LinphoneChatRoom* room = linphone_core_get_or_create_chat_room([LinphoneManager getLc], [dest UTF8String]);
[controller setChatRoom:room];
}
}
}

View file

@ -401,7 +401,8 @@ static UICompositeViewDescription *compositeDescription = nil;
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
if(controller != nil) {
[controller setRemoteAddress:[NSString stringWithUTF8String:lAddress]];
LinphoneChatRoom* room = linphone_core_get_or_create_chat_room([LinphoneManager getLc], lAddress);
[controller setChatRoom:room];
}
ms_free(lAddress);
}

View file

@ -256,6 +256,20 @@
[self processRemoteNotification:userInfo];
}
- (LinphoneChatRoom*)findChatRoomForContact:(NSString*)contact {
MSList* rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]);
const char* from = [contact UTF8String];
while (rooms) {
const LinphoneAddress* room_from_address = linphone_chat_room_get_peer_address((LinphoneChatRoom*)rooms->data);
char* room_from = linphone_address_as_string_uri_only(room_from_address);
if( room_from && strcmp(from, room_from)== 0){
return rooms->data;
}
rooms = rooms->next;
}
return NULL;
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[self fixRing];
@ -269,13 +283,14 @@
// auto answer only for non-timed local notifications
[[LinphoneManager instance] acceptCallForCallId:[notification.userInfo objectForKey:@"callId"]];
}
} else if([notification.userInfo objectForKey:@"chat"] != nil) {
NSString *remoteContact = (NSString*)[notification.userInfo objectForKey:@"chat"];
} else if([notification.userInfo objectForKey:@"from"] != nil) {
NSString *remoteContact = (NSString*)[notification.userInfo objectForKey:@"from"];
// Go to ChatRoom view
[[PhoneMainView instance] changeCurrentView:[ChatViewController compositeViewDescription]];
ChatRoomViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ChatRoomViewController compositeViewDescription] push:TRUE], ChatRoomViewController);
if(controller != nil) {
[controller setRemoteAddress:remoteContact];
LinphoneChatRoom*room = [self findChatRoomForContact:remoteContact];
[controller setChatRoom:room];
}
} else if([notification.userInfo objectForKey:@"callLog"] != nil) {
NSString *callLog = (NSString*)[notification.userInfo objectForKey:@"callLog"];

View file

@ -128,6 +128,7 @@ typedef struct _LinphoneManagerSounds {
+ (BOOL)isCodecSupported: (const char*)codecName;
+ (NSSet *)unsupportedCodecs;
+ (NSString *)getUserAgent;
+ (int)unreadMessageCount;
- (void)resetLinphoneCore;

View file

@ -29,7 +29,6 @@
#import "LinphoneManager.h"
#import "LinphoneCoreSettingsStore.h"
#import "ChatModel.h"
#include "linphone/linphonecore_utils.h"
#include "linphone/lpconfig.h"
@ -76,6 +75,9 @@ extern void libmsbcg729_init(void);
#define BACK_CAM_NAME "AV Capture: com.apple.avfoundation.avcapturedevice.built-in_video:0" /*"AV Capture: Back Camera"*/
NSString *const kLinphoneOldChatDBFilename = @"chat_database.sqlite";
NSString *const kLinphoneInternalChatDBFilename = @"linphone_chats.db";
@implementation LinphoneCallAppData
- (id)init {
if ((self = [super init])) {
@ -261,7 +263,6 @@ struct codec_name_pref_table codec_pref_table[]={
speakerEnabled = FALSE;
bluetoothEnabled = FALSE;
tunnelMode = FALSE;
[self openDatabase];
[self copyDefaultSettings];
pendindCallIdFromRemoteNotif = [[NSMutableArray alloc] init ];
photoLibrary = [[ALAssetsLibrary alloc] init];
@ -291,7 +292,6 @@ struct codec_name_pref_table codec_pref_table[]={
}
[fastAddressBook release];
[self closeDatabase];
[logs release];
OSStatus lStatus = AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, self);
@ -311,34 +311,85 @@ struct codec_name_pref_table codec_pref_table[]={
#pragma mark - Database Functions
- (void)openDatabase {
NSString *databasePath = [LinphoneManager documentFile:@"chat_database.sqlite"];
NSFileManager *filemgr = [NSFileManager defaultManager];
//[filemgr removeItemAtPath:databasePath error:nil];
BOOL firstInstall= ![filemgr fileExistsAtPath: databasePath ];
if(sqlite3_open([databasePath UTF8String], &database) != SQLITE_OK) {
[LinphoneLogger log:LinphoneLoggerError format:@"Can't open \"%@\" sqlite3 database.", databasePath];
return;
}
if (firstInstall) {
char *errMsg;
//better to create the db from the code
const char *sql_stmt = "CREATE TABLE chat (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT NOT NULL, time NUMERIC, read INTEGER, state INTEGER)";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't create table error[%s] ", errMsg];
}
}
}
- (void)migrateChatDBIfNeeded:(LinphoneCore*)lc {
sqlite3* newDb;
char *errMsg;
NSError* error;
NSString *oldDbPath = [LinphoneManager documentFile:kLinphoneOldChatDBFilename];
NSString *newDbPath = [LinphoneManager documentFile:kLinphoneInternalChatDBFilename];
BOOL shouldMigrate = [[NSFileManager defaultManager] fileExistsAtPath:oldDbPath];
LinphoneProxyConfig* default_proxy;
const char* identity = NULL;
- (void)closeDatabase {
if(database != NULL) {
if(sqlite3_close(database) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't close sqlite3 database."];
}
linphone_core_get_default_proxy(lc, &default_proxy);
if( !shouldMigrate ) return;
if( sqlite3_open([newDbPath UTF8String], &newDb) != SQLITE_OK) {
[LinphoneLogger log:LinphoneLoggerError format:@"Can't open \"%@\" sqlite3 database.", newDbPath];
return;
}
// attach old database to the new one:
char* attach_stmt = sqlite3_mprintf("ATTACH DATABASE %Q AS oldchats", [oldDbPath UTF8String]);
if( sqlite3_exec(newDb, attach_stmt, NULL, NULL, &errMsg) != SQLITE_OK ){
[LinphoneLogger logc:LinphoneLoggerError format:"Can't attach old chat table, error[%s] ", errMsg];
sqlite3_free(errMsg);
goto exit_dbmigration;
}
// migrate old chats to the new db
const char* migration_statement = "INSERT INTO history (localContact,remoteContact,direction,message,time,read,status) "
"SELECT localContact,remoteContact,direction,message,time,read,state FROM oldchats.chat";
if( sqlite3_exec(newDb, migration_statement, NULL, NULL, &errMsg) != SQLITE_OK ){
[LinphoneLogger logc:LinphoneLoggerError format:"DB migration failed, error[%s] ", errMsg];
sqlite3_free(errMsg);
goto exit_dbmigration;
}
// replace empty from: or to: by the current identity.
if( default_proxy ){
identity = linphone_proxy_config_get_identity(default_proxy);
}
if( !identity ){
identity = "sip:unknown@sip.linphone.org";
}
char* from_conversion = sqlite3_mprintf("UPDATE history SET localContact = %Q WHERE localContact = ''", identity);
if( sqlite3_exec(newDb, from_conversion, NULL, NULL, &errMsg) != SQLITE_OK ){
[LinphoneLogger logc:LinphoneLoggerError format:"FROM conversion failed, error[%s] ", errMsg];
sqlite3_free(errMsg);
}
sqlite3_free(from_conversion);
char* to_conversion = sqlite3_mprintf("UPDATE history SET remoteContact = %Q WHERE remoteContact = ''", identity);
if( sqlite3_exec(newDb, to_conversion, NULL, NULL, &errMsg) != SQLITE_OK ){
[LinphoneLogger logc:LinphoneLoggerError format:"DB migration failed, error[%s] ", errMsg];
sqlite3_free(errMsg);
}
sqlite3_free(to_conversion);
// move already stored images from the messages to the url field
const char* assetslib_migration = "UPDATE history SET url=message, message='' WHERE message LIKE 'assets-library%'";
if( sqlite3_exec(newDb, assetslib_migration, NULL, NULL, &errMsg) != SQLITE_OK ){
[LinphoneLogger logc:LinphoneLoggerError format:"Assets-history migration failed, error[%s] ", errMsg];
sqlite3_free(errMsg);
}
// We will lose received messages with remote url, they will be displayed in plain. We can't do much for them..
exit_dbmigration:
if( attach_stmt ) sqlite3_free(attach_stmt);
sqlite3_close(newDb);
// in any case, we should remove the old chat db
if(![[NSFileManager defaultManager] removeItemAtPath:oldDbPath error:&error] ){
[LinphoneLogger logc:LinphoneLoggerError format:"Could not remove old chat DB: %@", error];
}
}
@ -712,10 +763,6 @@ static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyCo
#pragma mark - Text Received Functions
- (void)onMessageReceived:(LinphoneCore *)lc room:(LinphoneChatRoom *)room message:(LinphoneChatMessage*)msg {
char *fromStr = linphone_address_as_string_uri_only(linphone_chat_message_get_from(msg));
if(fromStr == NULL)
return;
if (silentPushCompletion) {
@ -726,34 +773,20 @@ static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyCo
silentPushCompletion = nil;
}
// Save message in database
ChatModel *chat = [[ChatModel alloc] init];
[chat setLocalContact:@""];
[chat setRemoteContact:[NSString stringWithUTF8String:fromStr]];
if (linphone_chat_message_get_external_body_url(msg)) {
[chat setMessage:[NSString stringWithUTF8String:linphone_chat_message_get_external_body_url(msg)]];
} else {
[chat setMessage:[NSString stringWithUTF8String:linphone_chat_message_get_text(msg)]];
}
[chat setDirection:[NSNumber numberWithInt:1]];
[chat setTime:[NSDate dateWithTimeIntervalSince1970:linphone_chat_message_get_time(msg)]];
[chat setRead:[NSNumber numberWithInt:0]];
[chat create];
ms_free(fromStr);
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]
&& [UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
NSString* address = [chat remoteContact];
NSString *normalizedSipAddress = [FastAddressBook normalizeSipURI:address];
ABRecordRef contact = [fastAddressBook getContact:normalizedSipAddress];
const LinphoneAddress* remoteAddress = linphone_chat_message_get_from(msg);
char* c_address = linphone_address_as_string_uri_only(remoteAddress);
NSString* address = [NSString stringWithUTF8String:c_address];
NSString* from_address = [address copy];
ABRecordRef contact = [fastAddressBook getContact:address];
if(contact) {
address = [FastAddressBook getContactDisplayName:contact];
} else {
if ([[LinphoneManager instance] lpConfigBoolForKey:@"show_contacts_emails_preference"] == true) {
LinphoneAddress *linphoneAddress = linphone_address_new([normalizedSipAddress cStringUsingEncoding:[NSString defaultCStringEncoding]]);
LinphoneAddress *linphoneAddress = linphone_address_new([address cStringUsingEncoding:[NSString defaultCStringEncoding]]);
address = [NSString stringWithUTF8String:linphone_address_get_username(linphoneAddress)];
linphone_address_destroy(linphoneAddress);
}
@ -765,26 +798,23 @@ static void linphone_iphone_registration_state(LinphoneCore *lc, LinphoneProxyCo
// Create a new notification
UILocalNotification* notif = [[[UILocalNotification alloc] init] autorelease];
if (notif) {
notif.repeatInterval = 0;
notif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"IM_MSG",nil), address];
notif.alertAction = NSLocalizedString(@"Show", nil);
notif.soundName = @"msg.caf";
notif.userInfo = [NSDictionary dictionaryWithObject:[chat remoteContact] forKey:@"chat"];
notif.repeatInterval = 0;
notif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"IM_MSG",nil), address];
notif.alertAction = NSLocalizedString(@"Show", nil);
notif.soundName = @"msg.caf";
notif.userInfo = @{@"from":from_address };
[[UIApplication sharedApplication] presentLocalNotificationNow:notif];
}
[from_address release];
}
// Post event
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSValue valueWithPointer:room], @"room",
[NSValue valueWithPointer:linphone_chat_message_get_from(msg)], @"from",
chat.message, @"message",
chat, @"chat",
nil];
NSDictionary* dict = @{@"room" :[NSValue valueWithPointer:room],
@"from_address":[NSValue valueWithPointer:linphone_chat_message_get_from(msg)],
@"message" :[NSValue valueWithPointer:msg]};
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneTextReceived object:self userInfo:dict];
[chat release];
}
static void linphone_iphone_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message) {
@ -995,8 +1025,9 @@ static LinphoneCoreVTable linphonec_vtable = {
- (void)finishCoreConfiguration {
//get default config from bundle
NSString *zrtpSecretsFileName = [LinphoneManager documentFile:@"zrtp_secrets"];
const char* lRootCa = [[LinphoneManager bundleFile:@"rootca.pem"] cStringUsingEncoding:[NSString defaultCStringEncoding]];
NSString *zrtpSecretsFileName = [LinphoneManager documentFile:@"zrtp_secrets"];
NSString *chatDBFileName = [LinphoneManager documentFile:kLinphoneInternalChatDBFilename];
const char* lRootCa = [[LinphoneManager bundleFile:@"rootca.pem"] cStringUsingEncoding:[NSString defaultCStringEncoding]];
linphone_core_set_user_agent(theLinphoneCore,"LinphoneIPhone",
[[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey] UTF8String]);
@ -1016,6 +1047,9 @@ static LinphoneCoreVTable linphonec_vtable = {
linphone_core_set_play_file(theLinphoneCore, lPlay);
linphone_core_set_zrtp_secrets_file(theLinphoneCore, [zrtpSecretsFileName cStringUsingEncoding:[NSString defaultCStringEncoding]]);
linphone_core_set_chat_database_path(theLinphoneCore, [chatDBFileName cStringUsingEncoding:[NSString defaultCStringEncoding]]);
[self migrateChatDBIfNeeded:theLinphoneCore];
[self setupNetworkReachabilityCallback];
@ -1680,6 +1714,20 @@ static void audioRouteChangeListenerCallback (
return [documentsPath stringByAppendingPathComponent:file];
}
+ (int)unreadMessageCount {
int count = 0;
MSList* rooms = linphone_core_get_chat_rooms([LinphoneManager getLc]);
MSList* item = rooms;
while (item) {
LinphoneChatRoom* room = (LinphoneChatRoom*)item->data;
if( room ){
count += linphone_chat_room_get_unread_messages_count(room);
}
item = item->next;
}
return count;
}
+ (BOOL)copyFile:(NSString*)src destination:(NSString*)dst override:(BOOL)override {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;

View file

@ -20,13 +20,13 @@
#import <UIKit/UIKit.h>
#import "UITransparentTVCell.h"
#import "ChatModel.h"
#include "linphone/linphonecore.h"
@interface UIChatCell : UITransparentTVCell {
LinphoneChatRoom* chatRoom;
}
@property (nonatomic, retain) ChatModel *chat;
@property (nonatomic, retain) IBOutlet UIImageView *avatarImage;
@property (nonatomic, retain) IBOutlet UILabel* addressLabel;
@property (nonatomic, retain) IBOutlet UILabel* chatContentLabel;
@ -38,4 +38,5 @@
- (IBAction)onDeleteClick:(id)event;
- (void)setChatRoom:(LinphoneChatRoom *)achat;
@end

View file

@ -31,7 +31,6 @@
@synthesize unreadMessageLabel;
@synthesize unreadMessageView;
@synthesize chat;
#pragma mark - Lifecycle Functions
@ -57,24 +56,15 @@
[deleteButton release];
[unreadMessageLabel release];
[unreadMessageView release];
[chat release];
[super dealloc];
}
#pragma mark - Property Funcitons
- (void)setChat:(ChatModel *)achat {
if(chat == achat)
return;
if(chat != nil) {
[chat release];
}
if(achat) {
chat = [achat retain];
}
- (void)setChatRoom:(LinphoneChatRoom *)achat {
self->chatRoom = achat;
[self update];
}
@ -84,11 +74,12 @@
- (void)update {
NSString *displayName = nil;
UIImage *image = nil;
if(chat == nil) {
if(chatRoom == nil) {
[LinphoneLogger logc:LinphoneLoggerWarning format:"Cannot update chat cell: null chat"];
return;
}
LinphoneAddress* linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [[chat remoteContact] UTF8String]);
const LinphoneAddress* linphoneAddress = linphone_chat_room_get_peer_address(chatRoom);
if (linphoneAddress == NULL)
return;
char *tmp = linphone_address_as_string_uri_only(linphoneAddress);
@ -112,28 +103,39 @@
image = [UIImage imageNamed:@"avatar_unknown_small.png"];
}
[avatarImage setImage:image];
// Message
if([chat isExternalImage] || [chat isInternalImage]) {
[chatContentLabel setText:@""];
} else {
NSString *message = [chat message];
// shorten long messages
if([message length] > 50)
message = [[message substringToIndex:50] stringByAppendingString:@"[...]"];
[chatContentLabel setText:message];
}
int count = [ChatModel unreadMessages:[chat remoteContact]];
if(count > 0) {
[unreadMessageView setHidden:FALSE];
[unreadMessageLabel setText:[NSString stringWithFormat:@"%i", count]];
MSList* last_message_list = linphone_chat_room_get_history(chatRoom, 1);
LinphoneChatMessage* last_message = last_message_list? last_message_list->data : NULL;
if( last_message ){
const char* text = linphone_chat_message_get_text(last_message);
const char* url = linphone_chat_message_get_external_body_url(last_message);
// Message
if(url) {
[chatContentLabel setText:@""];
} else {
NSString *message = [NSString stringWithUTF8String:text];
// shorten long messages
if([message length] > 50)
message = [[message substringToIndex:50] stringByAppendingString:@"[...]"];
[chatContentLabel setText:message];
}
int count = linphone_chat_room_get_unread_messages_count(chatRoom);
if(count > 0) {
[unreadMessageView setHidden:FALSE];
[unreadMessageLabel setText:[NSString stringWithFormat:@"%i", count]];
} else {
[unreadMessageView setHidden:TRUE];
}
} else {
chatContentLabel.text = nil;
[unreadMessageView setHidden:TRUE];
}
linphone_address_destroy(linphoneAddress);
ms_list_free(last_message_list);
}
- (void)setEditing:(BOOL)editing {
@ -159,7 +161,7 @@
#pragma mark - Action Functions
- (IBAction)onDeleteClick: (id) event {
if(chat != NULL) {
if(chatRoom != NULL) {
UIView *view = [self superview];
// Find TableViewCell
while( view != nil && ![view isKindOfClass:[UITableView class]]) view = [view superview];

View file

@ -19,17 +19,17 @@
#import <UIKit/UIKit.h>
#import "ChatModel.h"
#import "ChatRoomTableViewController.h"
#import "UILoadingImageView.h"
#import "UITransparentTVCell.h"
#import "UITextViewNoDefine.h"
#include "linphone/linphonecore.h"
@interface UIChatRoomCell : UITransparentTVCell {
LinphoneChatMessage* chat;
}
@property (nonatomic, retain) ChatModel *chat;
@property (nonatomic, retain) IBOutlet UIView *innerView;
@property (nonatomic, retain) IBOutlet UIView *bubbleView;
@property (nonatomic, retain) IBOutlet UIImageView* backgroundImage;
@ -43,7 +43,7 @@
@property (nonatomic, retain) IBOutlet UITapGestureRecognizer* resendTapGestureRecognizer;
- (id)initWithIdentifier:(NSString*)identifier;
+ (CGFloat)height:(ChatModel*)chat width:(int)width;
+ (CGFloat)height:(LinphoneChatMessage*)chatMessage width:(int)width;
@property (nonatomic, retain) id<ChatRoomDelegate> chatRoomDelegate;
@ -51,4 +51,6 @@
- (IBAction)onDownloadClick:(id)event;
- (IBAction)onImageClick:(id)event;
- (void)setChatMessage:(LinphoneChatMessage*)message;
@end

View file

@ -37,7 +37,6 @@
@synthesize messageText;
@synthesize deleteButton;
@synthesize dateLabel;
@synthesize chat;
@synthesize statusImage;
@synthesize downloadButton;
@synthesize chatRoomDelegate;
@ -91,7 +90,6 @@ static UIFont *CELL_FONT = nil;
[deleteButton release];
[dateLabel release];
[statusImage release];
[chat release];
[downloadButton release];
[imageTapGestureRecognizer release];
[resendTapGestureRecognizer release];
@ -106,17 +104,8 @@ static UIFont *CELL_FONT = nil;
#pragma mark -
- (void)setChat:(ChatModel *)achat {
if(chat != achat) {
if(chat != nil) {
[chat release];
chat = nil;
}
if(achat != nil) {
chat = [achat retain];
}
}
- (void)setChatMessage:(LinphoneChatMessage *)message {
self->chat = message;
[self update];
}
@ -126,20 +115,23 @@ static UIFont *CELL_FONT = nil;
[LinphoneLogger logc:LinphoneLoggerWarning format:"Cannot update chat room cell: null chat"];
return;
}
if([chat isExternalImage]) {
const char*url = linphone_chat_message_get_external_body_url(chat);
const char*text = linphone_chat_message_get_text(chat);
BOOL is_external = url && (strstr(url, "http") == url);
if(is_external) {
[messageText setHidden:TRUE];
[messageImageView setImage:nil];
[messageImageView setHidden:TRUE];
[downloadButton setHidden:FALSE];
} else if([chat isInternalImage]) {
} else if(url) {
[messageText setHidden:TRUE];
[messageImageView setImage:nil];
[messageImageView startLoading];
ChatModel *achat = chat;
[[LinphoneManager instance].photoLibrary assetForURL:[NSURL URLWithString:[chat message]] resultBlock:^(ALAsset *asset) {
__block LinphoneChatMessage *achat = chat;
[[LinphoneManager instance].photoLibrary assetForURL:[NSURL URLWithString:[NSString stringWithUTF8String:url]] resultBlock:^(ALAsset *asset) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) {
ALAssetRepresentation* representation = [asset defaultRepresentation];
UIImage *image = [UIImage imageWithCGImage:[representation fullResolutionImage]
@ -161,7 +153,7 @@ static UIFont *CELL_FONT = nil;
[downloadButton setHidden:TRUE];
} else {
[messageText setHidden:FALSE];
[messageText setText:[chat message]];
[messageText setText:[NSString stringWithUTF8String:text]];
[messageImageView setImage:nil];
[messageImageView setHidden:TRUE];
@ -170,20 +162,24 @@ static UIFont *CELL_FONT = nil;
}
// Date
NSDate* message_date = [NSDate dateWithTimeIntervalSince1970:linphone_chat_message_get_time(chat)];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSLocale *locale = [NSLocale currentLocale];
[dateFormatter setLocale:locale];
[dateLabel setText:[dateFormatter stringFromDate:[chat time]]];
[dateLabel setText:[dateFormatter stringFromDate:message_date]];
[dateFormatter release];
if ([chat.state intValue] == LinphoneChatMessageStateInProgress) {
LinphoneChatMessageState state = linphone_chat_message_get_state(chat);
if (state== LinphoneChatMessageStateInProgress) {
[statusImage setImage:[UIImage imageNamed:@"chat_message_inprogress.png"]];
statusImage.hidden = FALSE;
} else if ([chat.state intValue] == LinphoneChatMessageStateDelivered) {
} else if (state == LinphoneChatMessageStateDelivered) {
[statusImage setImage:[UIImage imageNamed:@"chat_message_delivered.png"]];
statusImage.hidden = FALSE;
} else if ([chat.state intValue] == LinphoneChatMessageStateNotDelivered) {
} else if (state == LinphoneChatMessageStateNotDelivered) {
[statusImage setImage:[UIImage imageNamed:@"chat_message_not_delivered.png"]];
statusImage.hidden = FALSE;
@ -216,9 +212,12 @@ static UIFont *CELL_FONT = nil;
}
}
+ (CGSize)viewSize:(ChatModel*)chat width:(int)width {
+ (CGSize)viewSize:(LinphoneChatMessage*)chat width:(int)width {
CGSize messageSize;
if(!([chat isExternalImage] || [chat isInternalImage])) {
const char* url = linphone_chat_message_get_external_body_url(chat);
const char* text = linphone_chat_message_get_text(chat);
NSString* messageText = text ? [NSString stringWithUTF8String:text] : @"";
if(url == nil) {
if(CELL_FONT == nil) {
CELL_FONT = [UIFont systemFontOfSize:CELL_FONT_SIZE];
}
@ -226,7 +225,7 @@ static UIFont *CELL_FONT = nil;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
if( [[[UIDevice currentDevice] systemVersion] doubleValue] >= 7){
messageSize = [[chat message]
messageSize = [messageText
boundingRectWithSize:CGSizeMake(width - CELL_MESSAGE_X_MARGIN, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesFontLeading)
attributes:@{NSFontAttributeName: CELL_FONT}
@ -234,7 +233,7 @@ static UIFont *CELL_FONT = nil;
} else
#endif
{
messageSize = [[chat message] sizeWithFont: CELL_FONT
messageSize = [messageText sizeWithFont: CELL_FONT
constrainedToSize: CGSizeMake(width - CELL_MESSAGE_X_MARGIN, 10000.0f)
lineBreakMode: NSLineBreakByTruncatingTail];
}
@ -250,8 +249,8 @@ static UIFont *CELL_FONT = nil;
return messageSize;
}
+ (CGFloat)height:(ChatModel*)chat width:(int)width {
return [UIChatRoomCell viewSize:chat width:width].height;
+ (CGFloat)height:(LinphoneChatMessage*)chatMessage width:(int)width {
return [UIChatRoomCell viewSize:chatMessage width:width].height;
}
@ -262,8 +261,9 @@ static UIFont *CELL_FONT = nil;
if(chat != nil) {
// Resize inner
CGRect innerFrame;
BOOL is_outgoing = linphone_chat_message_is_outgoing(chat);
innerFrame.size = [UIChatRoomCell viewSize:chat width:[self frame].size.width];
if([[chat direction] intValue]) { // Inverted
if(is_outgoing) { // Inverted
innerFrame.origin.x = 0.0f;
innerFrame.origin.y = 0.0f;
} else {
@ -274,7 +274,7 @@ static UIFont *CELL_FONT = nil;
CGRect messageFrame = [bubbleView frame];
messageFrame.origin.y = ([innerView frame].size.height - messageFrame.size.height)/2;
if([[chat direction] intValue]) { // Inverted
if(is_outgoing) { // Inverted
[backgroundImage setImage:[TUNinePatchCache imageOfSize:[backgroundImage bounds].size
forNinePatchNamed:@"chat_bubble_incoming"]];
messageFrame.origin.y += 5;
@ -304,7 +304,9 @@ static UIFont *CELL_FONT = nil;
}
- (IBAction)onDownloadClick:(id)event {
[chatRoomDelegate chatRoomStartImageDownload:[NSURL URLWithString:chat.message] userInfo:chat];
NSURL* url = [NSURL URLWithString:[NSString stringWithUTF8String:linphone_chat_message_get_external_body_url(chat)]];
[chatRoomDelegate chatRoomStartImageDownload:url userInfo:[NSValue valueWithPointer:chat]];
}
- (IBAction)onImageClick:(id)event {
@ -317,14 +319,21 @@ static UIFont *CELL_FONT = nil;
}
- (IBAction)onResendClick:(id)event {
if ([chat.state intValue] == LinphoneChatMessageStateNotDelivered) {
NSString* message = [chat message];
if( chat == nil ) return;
LinphoneChatMessageState state = linphone_chat_message_get_state(self->chat);
if (state == LinphoneChatMessageStateNotDelivered) {
const char* text = linphone_chat_message_get_text(self->chat);
const char* url = linphone_chat_message_get_external_body_url(self->chat);
NSString* message = text ? [NSString stringWithUTF8String:text] : nil;
NSString* exturl = url ? [NSString stringWithUTF8String:url] : nil;
[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:message];
[chatRoomDelegate resendChat:message withExternalUrl:exturl];
});
}
}

View file

@ -19,7 +19,6 @@
#import "UIMainBar.h"
#import "PhoneMainView.h"
#import "ChatModel.h"
#import "CAAnimation+Blocks.h"
@implementation UIMainBar
@ -243,7 +242,7 @@ static NSString * const kDisappearAnimation = @"disappear";
}
- (void)textReceived:(NSNotification*)notif {
[self updateUnreadMessage:[ChatModel unreadMessages] appear:TRUE];
[self updateUnreadMessage:TRUE];
}
@ -256,10 +255,11 @@ static NSString * const kDisappearAnimation = @"disappear";
} else {
[self updateMissedCall:0 appear:TRUE];
}
[self updateUnreadMessage:[ChatModel unreadMessages] appear:appear];
[self updateUnreadMessage:appear];
}
- (void)updateUnreadMessage:(int)unreadMessage appear:(BOOL)appear{
- (void)updateUnreadMessage:(BOOL)appear{
int unreadMessage = [LinphoneManager unreadMessageCount];
if (unreadMessage > 0) {
if([chatNotificationView isHidden]) {
[chatNotificationView setHidden:FALSE];

View file

@ -1,59 +0,0 @@
/* ChatModel.h
*
* Copyright (C) 2012 Belledonne Comunications, Grenoble, France
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Foundation/Foundation.h>
@interface ChatModel : NSObject {
@private
NSNumber *chatId;
NSString *localContact;
NSString *remoteContact;
NSNumber *direction; //0 outgoing 1 incoming
NSString *message;
NSDate *time;
NSNumber *read;
NSNumber *state; //0 IDLE, 1 in progress, 2 delivered, 3 not delivered see LinphoneChatMessageState
}
@property (readonly) NSNumber *chatId;
@property (copy) NSString *localContact;
@property (copy) NSString *remoteContact;
@property (copy) NSNumber *direction;
@property (copy) NSString *message;
@property (copy) NSDate *time;
@property (copy) NSNumber *read;
@property (copy) NSNumber *state;
- (BOOL)isExternalImage;
- (BOOL)isInternalImage;
- (void)create;
+ (ChatModel*)read:(NSNumber*)id;
- (void)update;
- (void)delete;
+ (NSMutableArray *)listConversations;
+ (NSMutableArray *)listMessages:(NSString *)contact;
+ (void)removeConversation:(NSString *)contact;
+ (int)unreadMessages;
+ (int)unreadMessages:(NSString *)contact;
+ (void)readConversation:(NSString *)contact;
@end

View file

@ -1,379 +0,0 @@
/* ChatModel.m
*
* Copyright (C) 2012 Belledonne Comunications, Grenoble, France
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "ChatModel.h"
#import "LinphoneManager.h"
@implementation ChatModel
@synthesize chatId;
@synthesize localContact;
@synthesize remoteContact;
@synthesize message;
@synthesize direction;
@synthesize time;
@synthesize read;
@synthesize state;
#pragma mark - Lifecycle Functions
- (id)initWithData:(sqlite3_stmt *)sqlStatement {
self = [super init];
if (self != nil) {
self->chatId = [[NSNumber alloc] initWithInt: sqlite3_column_int(sqlStatement, 0)];
self.localContact = [NSString stringWithUTF8String: (const char*) sqlite3_column_text(sqlStatement, 1)];
self.remoteContact = [NSString stringWithUTF8String: (const char*) sqlite3_column_text(sqlStatement, 2)];
self.direction = [NSNumber numberWithInt:sqlite3_column_int(sqlStatement, 3)];
self.message = [NSString stringWithUTF8String: (const char*) sqlite3_column_text(sqlStatement, 4)];
self.time = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_int(sqlStatement, 5)];
self.read = [NSNumber numberWithInt:sqlite3_column_int(sqlStatement, 6)];
self.state = [NSNumber numberWithInt:sqlite3_column_int(sqlStatement, 7)];
}
return self;
}
- (void)dealloc {
[chatId release];
[localContact release];
[remoteContact release];
[message release];
[direction release];
[time release];
[read release];
[state release];
[super dealloc];
}
- (BOOL)isExternalImage {
return [message hasPrefix:@"http:"] || [message hasPrefix:@"https:"];
}
- (BOOL)isInternalImage {
return [message hasPrefix:@"assets-library:"];
}
#pragma mark - CRUD Functions
- (void)create {
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return;
}
const char *sql = "INSERT INTO chat (localContact, remoteContact, direction, message, time, read, state) VALUES (@LOCALCONTACT, @REMOTECONTACT, @DIRECTION, @MESSAGE, @TIME, @READ, @STATE)";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't prepare the query: %s (%s)", sql, sqlite3_errmsg(database)];
return;
}
// Prepare statement
sqlite3_bind_text(sqlStatement, 1, [localContact UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(sqlStatement, 2, [remoteContact UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_int(sqlStatement, 3, [direction intValue]);
sqlite3_bind_text(sqlStatement, 4, [message UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_double(sqlStatement, 5, [time timeIntervalSince1970]);
sqlite3_bind_int(sqlStatement, 6, [read intValue]);
sqlite3_bind_int(sqlStatement, 7, [state intValue]);
if (sqlite3_step(sqlStatement) != SQLITE_DONE) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
sqlite3_finalize(sqlStatement);
}
if([self chatId] != nil) {
[chatId release];
}
chatId = [[NSNumber alloc] initWithInt:(int)sqlite3_last_insert_rowid(database)];
sqlite3_finalize(sqlStatement);
}
+ (ChatModel*)read:(NSNumber*)chatId {
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return nil;
}
const char *sql = "SELECT id, localContact, remoteContact, direction, message, time, read FROM chat WHERE id=@ID";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't prepare the query: %s (%s)", sql, sqlite3_errmsg(database)];
return nil;
}
// Prepare statement
sqlite3_bind_int(sqlStatement, 1, [chatId intValue]);
ChatModel* line = nil;
int err = sqlite3_step(sqlStatement);
if (err == SQLITE_ROW) {
line = [[[ChatModel alloc] initWithData:sqlStatement] autorelease];
} else if (err != SQLITE_DONE) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
sqlite3_finalize(sqlStatement);
return nil;
}
sqlite3_finalize(sqlStatement);
return line;
}
- (void)update {
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return;
}
const char *sql = "UPDATE chat SET localContact=@LOCALCONTACT, remoteContact=@REMOTECONTACT, direction=@DIRECTION, message=@MESSAGE, time=@TIME, read=@READ, state=@STATE WHERE id=@ID";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't prepare the query: %s (%s)", sql, sqlite3_errmsg(database)];
return;
}
// Prepare statement
sqlite3_bind_text(sqlStatement, 1, [localContact UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(sqlStatement, 2, [remoteContact UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_int(sqlStatement, 3, [direction intValue]);
sqlite3_bind_text(sqlStatement, 4, [message UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_double(sqlStatement, 5, [time timeIntervalSince1970]);
sqlite3_bind_int(sqlStatement, 6, [read intValue]);
sqlite3_bind_int(sqlStatement, 7, [state intValue]);
sqlite3_bind_int(sqlStatement, 8, [chatId intValue]);
if (sqlite3_step(sqlStatement) != SQLITE_DONE) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
sqlite3_finalize(sqlStatement);
return;
}
sqlite3_finalize(sqlStatement);
}
- (void)delete {
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return;
}
const char *sql = "DELETE FROM chat WHERE id=@ID";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't prepare the query: %s (%s)", sql, sqlite3_errmsg(database)];
return;
}
// Prepare statement
sqlite3_bind_int(sqlStatement, 1, [chatId intValue]);
if (sqlite3_step(sqlStatement) != SQLITE_DONE) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
sqlite3_finalize(sqlStatement);
return;
}
sqlite3_finalize(sqlStatement);
}
#pragma mark -
+ (NSMutableArray *)listConversations {
NSMutableArray *array = [NSMutableArray array];
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return array;
}
const char *sql = "SELECT id, localContact, remoteContact, direction, message, time, read, state FROM chat GROUP BY remoteContact ORDER BY time DESC";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't execute the query: %s (%s)", sql, sqlite3_errmsg(database)];
return array;
}
int err;
while ((err = sqlite3_step(sqlStatement)) == SQLITE_ROW) {
ChatModel *line = [[ChatModel alloc] initWithData:sqlStatement];
[array addObject:line];
[line release];
}
if (err != SQLITE_DONE) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
return array;
}
sqlite3_finalize(sqlStatement);
return array;
}
+ (NSMutableArray *)listMessages:(NSString *)contact {
NSMutableArray *array = [NSMutableArray array];
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return array;
}
const char *sql = "SELECT id, localContact, remoteContact, direction, message, time, read, state FROM chat WHERE remoteContact=@REMOTECONTACT ORDER BY time ASC";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't execute the query: %s (%s)", sql, sqlite3_errmsg(database)];
return array;
}
// Prepare statement
sqlite3_bind_text(sqlStatement, 1, [contact UTF8String], -1, SQLITE_STATIC);
int err;
while ((err = sqlite3_step(sqlStatement)) == SQLITE_ROW) {
ChatModel *line = [[ChatModel alloc] initWithData:sqlStatement];
[array addObject:line];
[line release];
}
if (err != SQLITE_DONE) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
return array;
}
sqlite3_finalize(sqlStatement);
return array;
}
+ (void)removeConversation:(NSString *)contact {
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return;
}
const char *sql = "DELETE FROM chat WHERE remoteContact=@REMOTECONTACT";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't prepare the query: %s (%s)", sql, sqlite3_errmsg(database)];
return;
}
// Prepare statement
sqlite3_bind_text(sqlStatement, 1, [contact UTF8String], -1, SQLITE_STATIC);
if (sqlite3_step(sqlStatement) != SQLITE_DONE) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
sqlite3_finalize(sqlStatement);
return;
}
sqlite3_finalize(sqlStatement);
}
+ (int)unreadMessages {
int count = -1;
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return count;
}
const char *sql = "SELECT count(*) FROM chat WHERE read=0";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't prepare the query: %s (%s)", sql, sqlite3_errmsg(database)];
return count;
}
if (sqlite3_step(sqlStatement) != SQLITE_ROW) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
sqlite3_finalize(sqlStatement);
return count;
}
count = sqlite3_column_int(sqlStatement, 0);
sqlite3_finalize(sqlStatement);
return count;
}
+ (int)unreadMessages:(NSString *)contact {
int count = -1;
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return count;
}
const char *sql = "SELECT count(*) FROM chat WHERE read=0 AND remoteContact=@REMOTECONTACT";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't prepare the query: %s (%s)", sql, sqlite3_errmsg(database)];
return count;
}
// Prepare statement
sqlite3_bind_text(sqlStatement, 1, [contact UTF8String], -1, SQLITE_STATIC);
if (sqlite3_step(sqlStatement) != SQLITE_ROW) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
sqlite3_finalize(sqlStatement);
return count;
}
count = sqlite3_column_int(sqlStatement, 0);
sqlite3_finalize(sqlStatement);
return count;
}
+ (void)readConversation:(NSString *)contact {
sqlite3* database = [[LinphoneManager instance] database];
if(database == NULL) {
[LinphoneLogger logc:LinphoneLoggerError format:"Database not ready"];
return;
}
const char *sql = "UPDATE chat SET read=1 WHERE remoteContact=@REMOTECONTACT";
sqlite3_stmt *sqlStatement;
if (sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
[LinphoneLogger logc:LinphoneLoggerError format:"Can't prepare the query: %s (%s)", sql, sqlite3_errmsg(database)];
return;
}
// Prepare statement
sqlite3_bind_text(sqlStatement, 1, [contact UTF8String], -1, SQLITE_STATIC);
if (sqlite3_step(sqlStatement) != SQLITE_DONE) {
[LinphoneLogger logc:LinphoneLoggerError format:"Error during execution of query: %s (%s)", sql, sqlite3_errmsg(database)];
sqlite3_finalize(sqlStatement);
return;
}
sqlite3_finalize(sqlStatement);
}
@end

View file

@ -219,9 +219,9 @@ static PhoneMainView* phoneMainViewInstance=nil;
#pragma mark - Event Functions
- (void)textReceived:(NSNotification*)notif {
ChatModel *chat = [[notif userInfo] objectForKey:@"chat"];
if(chat != nil) {
[self displayMessage:chat];
LinphoneAddress*from = [[notif.userInfo objectForKey:@"from_address"] pointerValue];
if(from != nil) {
[self playMessageSound];
}
[self updateApplicationBadgeNumber];
}
@ -377,7 +377,7 @@ static PhoneMainView* phoneMainViewInstance=nil;
- (void)updateApplicationBadgeNumber {
int count = 0;
count += linphone_core_get_missed_calls_count([LinphoneManager getLc]);
count += [ChatModel unreadMessages];
count += [LinphoneManager unreadMessageCount];
count += linphone_core_get_calls_nb([LinphoneManager getLc]);
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:count];
}
@ -598,7 +598,7 @@ static PhoneMainView* phoneMainViewInstance=nil;
#pragma mark - ActionSheet Functions
- (void)displayMessage:(ChatModel*)chat {
- (void)playMessageSound {
if (![[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]
|| [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
if(![self removeInhibitedEvent:kLinphoneTextReceived]) {