handle user notifications in app extension

This commit is contained in:
Paul Cartier 2020-04-10 17:05:15 +02:00
parent 972aabfe05
commit 7ed3c5bbf7
9 changed files with 28 additions and 292 deletions

View file

@ -1121,7 +1121,6 @@ void on_chat_room_chat_message_sent(LinphoneChatRoom *cr, const LinphoneEventLog
ChatConversationView *view = (__bridge ChatConversationView *)linphone_chat_room_cbs_get_user_data(linphone_chat_room_get_current_callbacks(cr));
[view.tableController addEventEntry:(LinphoneEventLog *)event_log];
[view.tableController scrollToBottom:true];
[ChatsListTableView saveDataToUserDefaults];
if (IPAD)
[NSNotificationCenter.defaultCenter postNotificationName:kLinphoneMessageReceived object:view];

View file

@ -30,5 +30,4 @@
- (void)loadData;
- (void)markCellAsRead:(LinphoneChatRoom *)chatRoom;
+ (void)saveDataToUserDefaults;
@end

View file

@ -19,7 +19,6 @@
#import "ChatsListTableView.h"
#import "UIChatCell.h"
#import "FileTransferDelegate.h"
#import "linphone/linphonecore.h"
@ -126,75 +125,6 @@ static int sorted_history_comparison(LinphoneChatRoom *to_insert, LinphoneChatRo
}
}
+ (void) saveDataToUserDefaults {
// As extensions is disabled by default, this function takes too much CPU.
#if 0
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.belledonne-communications.linphone.widget"];
MSList *sorted = nil;
const MSList *unsorted = linphone_core_get_chat_rooms(LC);
const MSList *iter = unsorted;
while (iter) {
// store last message in user data
LinphoneChatRoom *chat_room = iter->data;
sorted = bctbx_list_insert_sorted(sorted, chat_room, (bctbx_compare_func)sorted_history_comparison);
iter = iter->next;
}
NSMutableArray *addresses = [NSMutableArray array];
while (sorted) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
LinphoneChatRoom *cr = sorted->data;
if (!cr) {
sorted = sorted->next;
continue;
}
const LinphoneAddress *peer_address = linphone_chat_room_get_peer_address(cr);
const LinphoneAddress *local_address = linphone_chat_room_get_local_address(cr);
NSString *display;
[dict setObject:[NSString stringWithUTF8String:linphone_address_as_string_uri_only(peer_address)]
forKey:@"peer"];
[dict setObject:local_address?[NSString stringWithUTF8String:linphone_address_as_string_uri_only(local_address)]:@""
forKey:@"local"];
LinphoneChatRoomCapabilitiesMask capabilities = linphone_chat_room_get_capabilities(cr);
if (!(capabilities & LinphoneChatRoomCapabilitiesOneToOne)) {
if (!linphone_chat_room_get_subject(cr)) {
sorted = sorted->next;
continue;
}
display = [NSString stringWithUTF8String:linphone_chat_room_get_subject(cr)];
} else {
bctbx_list_t *participants = linphone_chat_room_get_participants(cr);
LinphoneParticipant *firstParticipant = participants ? (LinphoneParticipant *)participants->data : NULL;
const LinphoneAddress *addr = firstParticipant ? linphone_participant_get_address(firstParticipant) : peer_address;
if (!linphone_address_get_username(addr)) {
sorted = sorted->next;
continue;
}
display = [NSString stringWithUTF8String:linphone_address_get_display_name(addr)?:linphone_address_get_username(addr)];
if ([FastAddressBook imageForAddress:addr])
[dict setObject:UIImageJPEGRepresentation([UIImage resizeImage:[FastAddressBook imageForAddress:peer_address]
withMaxWidth:200
andMaxHeight:200],
1)
forKey:@"img"];
}
[dict setObject:display
forKey:@"display"];
BOOL isGroupChat = linphone_chat_room_get_capabilities(cr) & LinphoneChatRoomCapabilitiesConference;
[dict setObject:[NSNumber numberWithBool:isGroupChat]
forKey:@"nbParticipants"];
[addresses addObject:dict];
if (addresses.count >= 4) //send no more data than needed
break;
sorted = sorted->next;
}
[defaults setObject:addresses forKey:@"chatrooms"];
#endif
}
- (void)markCellAsRead:(LinphoneChatRoom *)chatRoom {
int idx = bctbx_list_index(_data, VIEW(ChatConversationView).chatRoom);
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];

View file

@ -28,6 +28,4 @@
@property(strong, nonatomic) NSMutableDictionary *sections;
@property(strong, nonatomic) NSMutableArray *sortedDays;
+ (void) saveDataToUserDefaults;
@end

View file

@ -167,67 +167,6 @@
}
}
+ (void) saveDataToUserDefaults {
// As extensions is disabled by default, this function takes too much CPU.
#if 0
const bctbx_list_t *logs = linphone_core_get_call_logs(LC);
NSUserDefaults *mySharedDefaults = [[NSUserDefaults alloc] initWithSuiteName: @"group.belledonne-communications.linphone.widget"];
NSMutableArray *logsShare = [NSMutableArray array];
NSMutableDictionary *tmpStoreDict = [NSMutableDictionary dictionary];
NSMutableArray *addedContacts = [NSMutableArray array];
while (logs) {
LinphoneCallLog *log = (LinphoneCallLog *)logs->data;
const LinphoneAddress *address = linphone_call_log_get_remote_address(log);
// if contact is already to be display, skip
if ([addedContacts containsObject:[NSString stringWithUTF8String:linphone_address_as_string_uri_only(address)]]) {
logs = bctbx_list_next(logs);
continue;
}
// if null log id, skip
if (!linphone_call_log_get_call_id(log)) {
logs = bctbx_list_next(logs);
continue;
}
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSString stringWithUTF8String:linphone_call_log_get_call_id(log)]
forKey:@"id"];
[dict setObject:[NSString stringWithUTF8String:linphone_address_get_display_name(address)?:(linphone_address_get_username(address)?:"unknown")]
forKey:@"display"];
UIImage *avatar = [FastAddressBook imageForAddress:address];
if (avatar) {
UIImage *image = [UIImage resizeImage:avatar
withMaxWidth:200
andMaxHeight:200];
NSData *imageData = UIImageJPEGRepresentation(image, 1);
[dict setObject:imageData
forKey:@"img"];
}
[tmpStoreDict setObject:dict
forKey:[NSDate dateWithTimeIntervalSince1970:linphone_call_log_get_start_date(log)]];
[addedContacts addObject:[NSString stringWithUTF8String:linphone_address_as_string_uri_only(address)]];
logs = bctbx_list_next(logs);
}
NSArray *sortedDates = [[NSMutableArray alloc]
initWithArray:[tmpStoreDict.allKeys sortedArrayUsingComparator:^NSComparisonResult(NSDate *d1, NSDate *d2) {
return [d2 compare:d1];
}]];
// sort logs array on date
for (NSDate *date in sortedDates) {
[logsShare addObject:[tmpStoreDict objectForKey:date]];
if (logsShare.count >= 4) //send no more data than needed
break;
}
[mySharedDefaults setObject:logsShare forKey:@"logs"];
#endif
}
- (void)computeSections {
NSArray *unsortedDays = [self.sections allKeys];
_sortedDays = [[NSMutableArray alloc]

View file

@ -145,8 +145,6 @@
[self handleShortcut:_shortcutItem];
_shortcutItem = nil;
}
[HistoryListTableView saveDataToUserDefaults];
[ChatsListTableView saveDataToUserDefaults];
}
#pragma deploymate push "ignored-api-availability"
@ -575,6 +573,23 @@
return;
}
if (category && [category isEqualToString:@"msg_cat"] && [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
if ((PhoneMainView.instance.currentView == ChatsListView.compositeViewDescription))
return;
if (PhoneMainView.instance.currentView == ChatConversationView.compositeViewDescription) {
NSDictionary *userInfo = [[[notification request] content] userInfo];
NSString *peerAddress = userInfo[@"peer_addr"];
NSString *localAddress = userInfo[@"local_addr"];
if (peerAddress && localAddress) {
LinphoneAddress *peer = linphone_core_create_address([LinphoneManager getLc], peerAddress.UTF8String);
LinphoneAddress *local = linphone_core_create_address([LinphoneManager getLc], localAddress.UTF8String);
LinphoneChatRoom *room = linphone_core_find_chat_room([LinphoneManager getLc], peer, local);
if (room == PhoneMainView.instance.currentRoom) return;
}
}
}
completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionAlert);
}

View file

@ -60,7 +60,7 @@ extern NSString *const kLinphoneFileTransferRecvUpdate;
extern NSString *const kLinphoneQRCodeFound;
extern NSString *const kLinphoneChatCreateViewChange;
extern NSString *const kLinphoneMsgNotificationGroupId;
extern NSString *const kLinphoneMsgNotificationAppGroupId;
typedef enum _NetworkType {
network_none = 0,

View file

@ -856,140 +856,6 @@ static void linphone_iphone_popup_password_request(LinphoneCore *lc, LinphoneAut
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
return;
}
// Create a new notification
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
NSArray *actions;
if ([[UIDevice.currentDevice systemVersion] floatValue] < 9 ||
[LinphoneManager.instance lpConfigBoolForKey:@"show_msg_in_notif"] == NO) {
UIMutableUserNotificationAction *reply = [[UIMutableUserNotificationAction alloc] init];
reply.identifier = @"reply";
reply.title = NSLocalizedString(@"Reply", nil);
reply.activationMode = UIUserNotificationActivationModeForeground;
reply.destructive = NO;
reply.authenticationRequired = YES;
UIMutableUserNotificationAction *mark_read = [[UIMutableUserNotificationAction alloc] init];
mark_read.identifier = @"mark_read";
mark_read.title = NSLocalizedString(@"Mark Read", nil);
mark_read.activationMode = UIUserNotificationActivationModeBackground;
mark_read.destructive = NO;
mark_read.authenticationRequired = NO;
actions = @[ mark_read, reply ];
} else {
// iOS 9 allows for inline reply. We don't propose mark_read in this case
UIMutableUserNotificationAction *reply_inline = [[UIMutableUserNotificationAction alloc] init];
reply_inline.identifier = @"reply_inline";
reply_inline.title = NSLocalizedString(@"Reply", nil);
reply_inline.activationMode = UIUserNotificationActivationModeBackground;
reply_inline.destructive = NO;
reply_inline.authenticationRequired = NO;
reply_inline.behavior = UIUserNotificationActionBehaviorTextInput;
actions = @[ reply_inline ];
}
UIMutableUserNotificationCategory *msgcat = [[UIMutableUserNotificationCategory alloc] init];
msgcat.identifier = @"incoming_msg";
[msgcat setActions:actions forContext:UIUserNotificationActionContextDefault];
[msgcat setActions:actions forContext:UIUserNotificationActionContextMinimal];
NSSet *categories = [NSSet setWithObjects:msgcat, nil];
UIUserNotificationSettings *set = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound)
categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:set];
UILocalNotification *notif = [[UILocalNotification alloc] init];
if (notif) {
NSString *chat = [UIChatBubbleTextCell TextMessageForChat:msg];
notif.repeatInterval = 0;
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8) {
#pragma deploymate push "ignored-api-availability"
notif.category = @"incoming_msg";
#pragma deploymate pop
}
if ([LinphoneManager.instance lpConfigBoolForKey:@"show_msg_in_notif" withDefault:YES]) {
notif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"IM_FULLMSG", nil), from, chat];
} else {
notif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"IM_MSG", nil), from];
}
notif.alertAction = NSLocalizedString(@"Show", nil);
notif.soundName = @"msg.caf";
notif.userInfo = @{@"from" : from, @"peer_addr" : peer_uri, @"local_addr" : local_uri, @"call-id" : callID};
notif.accessibilityLabel = @"Message notif";
[[UIApplication sharedApplication] presentLocalNotificationNow:notif];
}
} else {
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = NSLocalizedString(@"Message received", nil);
const char* subject = linphone_chat_room_get_subject(room) ?: LINPHONE_DUMMY_SUBJECT;
if ([LinphoneManager.instance lpConfigBoolForKey:@"show_msg_in_notif" withDefault:YES]) {
content.subtitle = strcmp(subject, LINPHONE_DUMMY_SUBJECT) != 0 ? [NSString stringWithUTF8String:subject] : fromMsg;
content.body = strcmp(subject, LINPHONE_DUMMY_SUBJECT) != 0
? [NSString stringWithFormat:@"%@ : %@", fromMsg, [UIChatBubbleTextCell TextMessageForChat:msg]]
: [UIChatBubbleTextCell TextMessageForChat:msg];
} else {
content.body = strcmp(subject, LINPHONE_DUMMY_SUBJECT) != 0
? [NSString stringWithFormat:@"%@ : %@",[NSString stringWithUTF8String:subject], fromMsg]
: fromMsg;
}
content.sound = [UNNotificationSound soundNamed:@"msg.caf"];
content.categoryIdentifier = @"msg_cat";
// save data to user info for rich notification content
NSMutableArray *msgs = [NSMutableArray array];
bctbx_list_t *history = linphone_chat_room_get_history(room, 6);
while (history) {
NSMutableDictionary *msgData = [NSMutableDictionary dictionary];
LinphoneChatMessage *msg = history->data;
const char *state = linphone_chat_message_state_to_string(linphone_chat_message_get_state(msg));
bool_t isOutgoing = linphone_chat_message_is_outgoing(msg);
bool_t isFileTransfer = (linphone_chat_message_get_file_transfer_information(msg) != NULL);
const LinphoneAddress *fromAddress = linphone_chat_message_get_from_address(msg);
NSString *displayNameDate = [NSString stringWithFormat:@"%@ - %@", [LinphoneUtils timeToString:linphone_chat_message_get_time(msg)
withFormat:LinphoneDateChatBubble],
[FastAddressBook displayNameForAddress:fromAddress]];
UIImage *fromImage = [UIImage resizeImage:[FastAddressBook imageForAddress:fromAddress]
withMaxWidth:200
andMaxHeight:200];
NSData *fromImageData = UIImageJPEGRepresentation(fromImage, 1);
[msgData setObject:[NSString stringWithUTF8String:state] forKey:@"state"];
[msgData setObject:displayNameDate forKey:@"displayNameDate"];
[msgData setObject:[NSNumber numberWithBool:isFileTransfer] forKey:@"isFileTransfer"];
[msgData setObject:fromImageData forKey:@"fromImageData"];
if (isFileTransfer) {
LinphoneContent *file = linphone_chat_message_get_file_transfer_information(msg);
const char *filename = linphone_content_get_name(file);
[msgData setObject:[NSString stringWithUTF8String:filename] forKey:@"msg"];
} else {
[msgData setObject:[UIChatBubbleTextCell TextMessageForChat:msg] forKey:@"msg"];
}
[msgData setObject:[NSNumber numberWithBool:isOutgoing] forKey:@"isOutgoing"];
[msgs addObject:msgData];
history = bctbx_list_next(history);
}
content.userInfo = @{@"from" : from, @"peer_addr" : peer_uri, @"local_addr" : local_uri, @"CallId" : callID, @"msgs" : msgs};
content.accessibilityLabel = @"Message notif";
UNNotificationRequest *req = [UNNotificationRequest requestWithIdentifier:@"call_request" content:content trigger:NULL];
[[UNUserNotificationCenter currentNotificationCenter]
addNotificationRequest:req
withCompletionHandler:^(NSError *_Nullable error) {
// Enable or disable features based on authorization.
if (error) {
LOGD(@"Error while adding notification request :");
LOGD(error.description);
}
}];
}
[ChatsListTableView saveDataToUserDefaults];
[HistoryListTableView saveDataToUserDefaults];
}
static void linphone_iphone_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message) {
[(__bridge LinphoneManager *)linphone_core_cbs_get_user_data(linphone_core_get_current_callbacks(lc)) onMessageReceived:lc room:room message:message];
}
static void linphone_iphone_message_received_unable_decrypt(LinphoneCore *lc, LinphoneChatRoom *room,
@ -1283,9 +1149,6 @@ static void linphone_iphone_is_composing_received(LinphoneCore *lc, LinphoneChat
[self enableProxyPublish:([UIApplication sharedApplication].applicationState == UIApplicationStateActive)];
//update UserDefaults for widgets
[HistoryListTableView saveDataToUserDefaults];
LOGI(@"Linphone [%s] started on [%s]", linphone_core_get_version(), [[UIDevice currentDevice].model UTF8String]);
// Post event
@ -1446,7 +1309,6 @@ void popup_link_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreat
linphone_core_cbs_set_registration_state_changed(cbs,linphone_iphone_registration_state);
linphone_core_cbs_set_notify_presence_received_for_uri_or_tel(cbs, linphone_iphone_notify_presence_received_for_uri_or_tel);
linphone_core_cbs_set_authentication_requested(cbs, linphone_iphone_popup_password_request);
linphone_core_cbs_set_message_received(cbs, linphone_iphone_message_received);
linphone_core_cbs_set_message_received_unable_decrypt(cbs, linphone_iphone_message_received_unable_decrypt);
linphone_core_cbs_set_transfer_state_changed(cbs, linphone_iphone_transfer_state_changed);
linphone_core_cbs_set_is_composing_received(cbs, linphone_iphone_is_composing_received);

View file

@ -86,10 +86,10 @@ class NotificationService: UNNotificationServiceExtension {
NotificationService.log.message(msg: "fetch msg for callid ["+callId+"]")
let message = lc!.getNewMessageFromCallid(callId: callId)
if let message = message, let chatRoom = message.chatRoom {
let msgData = parseMessage(room: chatRoom, message: message)
if let message = message {
let msgData = parseMessage(message: message)
if let badge = updateBadge() as NSNumber? {
if !message.isUsingUserDefaults, let badge = updateBadge() as NSNumber? {
bestAttemptContent.badge = badge
}
@ -142,23 +142,17 @@ class NotificationService: UNNotificationServiceExtension {
}
}
func parseMessage(room: ChatRoom, message: ChatMessage) -> MsgData? {
NotificationService.log.message(msg: "Core received msg \(message.contentType) \n")
if (message.contentType != "text/plain" && message.contentType != "image/jpeg") {
return nil
}
func parseMessage(message: PushNotificationMessage) -> MsgData? {
let content = message.isText ? message.textContent : "🗻"
let from = message.fromAddress?.username
let callId = message.getCustomHeader(headerName: "Call-Id")
let localUri = room.localAddress?.asStringUriOnly()
let peerUri = room.peerAddress?.asStringUriOnly()
let from = message.fromAddr?.username
let callId = message.callId
let localUri = message.localAddr?.asStringUriOnly()
let peerUri = message.peerAddr?.asStringUriOnly()
var msgData = MsgData(from: from, body: "", subtitle: "", callId:callId, localAddr: localUri, peerAddr:peerUri)
if let showMsg = lc!.config?.getBool(section: "app", key: "show_msg_in_notif", defaultValue: true), showMsg == true {
if let subject = room.subject as String?, subject != "" {
if let subject = message.subject as String?, subject != "" {
msgData.subtitle = subject
msgData.body = from! + " : " + content
} else {
@ -166,7 +160,7 @@ class NotificationService: UNNotificationServiceExtension {
msgData.body = content
}
} else {
if let subject = room.subject as String?, subject != "" {
if let subject = message.subject as String?, subject != "" {
msgData.body = subject + " : " + from!
} else {
msgData.body = from