Notification titles for iOS10+

This commit is contained in:
Michael Kirk 2019-01-30 19:11:56 -07:00
parent 1dbb9849c5
commit d88ffc4775
7 changed files with 144 additions and 122 deletions

View File

@ -115,8 +115,8 @@ protocol NotificationPresenterAdaptee: class {
func registerNotificationSettings() -> Promise<Void>
func notify(category: AppNotificationCategory, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?)
func notify(category: AppNotificationCategory, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?, replacingIdentifier: String?)
func notify(category: AppNotificationCategory, title: String?, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?)
func notify(category: AppNotificationCategory, title: String?, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?, replacingIdentifier: String?)
func cancelNotifications(threadId: String)
func clearAllNotifications()
@ -210,14 +210,15 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
}
func presentIncomingCall(_ call: SignalCall, callerName: String) {
let alertMessage: String
let notificationTitle: String?
switch previewType {
case .noNameNoPreview:
alertMessage = CallStrings.incomingCallWithoutCallerNameNotification
notificationTitle = nil
case .nameNoPreview, .namePreview:
alertMessage = String(format: CallStrings.incomingCallNotificationFormat, callerName)
notificationTitle = callerName
}
let notificationBody = "☎️".rtlSafeAppend(" ").rtlSafeAppend(alertMessage)
let notificationBody = NotificationStrings.incomingCallBody
let remotePhoneNumber = call.remotePhoneNumber
let thread = TSContactThread.getOrCreateThread(contactId: remotePhoneNumber)
@ -234,6 +235,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
DispatchQueue.main.async {
self.adaptee.notify(category: .incomingCall,
title: notificationTitle,
body: notificationBody,
userInfo: userInfo,
sound: .defaultiOSIncomingRingtone,
@ -242,13 +244,14 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
}
func presentMissedCall(_ call: SignalCall, callerName: String) {
let notificationBody: String
let notificationTitle: String?
switch previewType {
case .noNameNoPreview:
notificationBody = CallStrings.missedCallNotificationBodyWithoutCallerName
notificationTitle = nil
case .nameNoPreview, .namePreview:
notificationBody = String(format: CallStrings.missedCallNotificationBodyWithCallerName, callerName)
notificationTitle = callerName
}
let notificationBody = NotificationStrings.missedCallBody
let remotePhoneNumber = call.remotePhoneNumber
let thread = TSContactThread.getOrCreateThread(contactId: remotePhoneNumber)
@ -266,6 +269,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
DispatchQueue.main.async {
let sound = self.requestSound(thread: thread)
self.adaptee.notify(category: .missedCall,
title: notificationTitle,
body: notificationBody,
userInfo: userInfo,
sound: sound,
@ -274,13 +278,14 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
}
public func presentMissedCallBecauseOfNoLongerVerifiedIdentity(call: SignalCall, callerName: String) {
let notificationBody: String
let notificationTitle: String?
switch previewType {
case .noNameNoPreview:
notificationBody = CallStrings.missedCallWithIdentityChangeNotificationBodyWithoutCallerName
notificationTitle = nil
case .nameNoPreview, .namePreview:
notificationBody = String(format: CallStrings.missedCallWithIdentityChangeNotificationBodyWithCallerName, callerName)
notificationTitle = callerName
}
let notificationBody = NotificationStrings.missedCallBecauseOfIdentityChangeBody
let remotePhoneNumber = call.remotePhoneNumber
let thread = TSContactThread.getOrCreateThread(contactId: remotePhoneNumber)
@ -296,6 +301,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
DispatchQueue.main.async {
let sound = self.requestSound(thread: thread)
self.adaptee.notify(category: .missedCallFromNoLongerVerifiedIdentity,
title: notificationTitle,
body: notificationBody,
userInfo: userInfo,
sound: sound,
@ -304,14 +310,14 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
}
public func presentMissedCallBecauseOfNewIdentity(call: SignalCall, callerName: String) {
let notificationBody: String
let notificationTitle: String?
switch previewType {
case .noNameNoPreview:
notificationBody = CallStrings.missedCallWithIdentityChangeNotificationBodyWithoutCallerName
notificationTitle = nil
case .nameNoPreview, .namePreview:
notificationBody = String(format: CallStrings.missedCallWithIdentityChangeNotificationBodyWithCallerName, callerName)
notificationTitle = callerName
}
let notificationBody = NotificationStrings.missedCallBecauseOfIdentityChangeBody
let remotePhoneNumber = call.remotePhoneNumber
let thread = TSContactThread.getOrCreateThread(contactId: remotePhoneNumber)
@ -329,6 +335,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
DispatchQueue.main.async {
let sound = self.requestSound(thread: thread)
self.adaptee.notify(category: .missedCall,
title: notificationTitle,
body: notificationBody,
userInfo: userInfo,
sound: sound,
@ -354,46 +361,34 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
let senderName = contactsManager.displayName(forPhoneIdentifier: incomingMessage.authorId)
let notificationBody: String
let notificationTitle: String?
switch previewType {
case .noNameNoPreview:
notificationBody = NSLocalizedString("APN_Message", comment: "")
case .nameNoPreview:
notificationTitle = nil
case .nameNoPreview, .namePreview:
switch thread {
case is TSContactThread:
// TODO - should this be a format string? seems weird we're hardcoding in a ":"
let fromText = NSLocalizedString("APN_MESSAGE_FROM", comment: "")
notificationBody = String(format: "%@: %@", fromText, senderName)
notificationTitle = senderName
case is TSGroupThread:
var groupName = thread.name()
if groupName.count < 1 {
groupName = MessageStrings.newGroupDefaultTitle
}
// TODO - should this be a format string? seems weird we're hardcoding in the quotes
let fromText = NSLocalizedString("APN_MESSAGE_IN_GROUP", comment: "")
notificationBody = String(format: "%@ \"%@\"", fromText, groupName)
notificationTitle = String(format: NotificationStrings.incomingGroupMessageTitleFormat,
senderName,
groupName)
default:
owsFailDebug("unexpected thread: \(thread)")
return
}
case .namePreview:
switch thread {
case is TSContactThread:
notificationBody = String(format: "%@: %@", senderName, messageText ?? "")
case is TSGroupThread:
var groupName = thread.name()
if groupName.count < 1 {
groupName = MessageStrings.newGroupDefaultTitle
}
let threadName = String(format: "\"%@\"", groupName)
}
let bodyFormat = NSLocalizedString("APN_MESSAGE_IN_GROUP_DETAILED", comment: "")
notificationBody = String(format: bodyFormat, senderName, threadName, messageText ?? "")
default:
owsFailDebug("unexpected thread: \(thread)")
return
}
let notificationBody: String?
switch previewType {
case .noNameNoPreview, .nameNoPreview:
notificationBody = NotificationStrings.incomingMessageBody
case .namePreview:
notificationBody = messageText
}
guard let threadId = thread.uniqueId else {
@ -401,6 +396,8 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
return
}
assert((notificationBody ?? notificationTitle) != nil)
// Don't reply from lockscreen if anyone in this conversation is
// "no longer verified".
var category = AppNotificationCategory.incomingMessage
@ -417,13 +414,24 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
DispatchQueue.main.async {
let sound = self.requestSound(thread: thread)
self.adaptee.notify(category: category, body: notificationBody, userInfo: userInfo, sound: sound)
self.adaptee.notify(category: category,
title: notificationTitle,
body: notificationBody ?? "",
userInfo: userInfo,
sound: sound)
}
}
public func notifyForFailedSend(inThread thread: TSThread) {
let notificationFormat = NSLocalizedString("NOTIFICATION_SEND_FAILED", comment: "subsequent notification body when replying from notification fails")
let notificationBody = String(format: notificationFormat, thread.name())
let notificationTitle: String?
switch previewType {
case .noNameNoPreview:
notificationTitle = nil
case .nameNoPreview, .namePreview:
notificationTitle = thread.name()
}
let notificationBody = NotificationStrings.failedToSendBody
guard let threadId = thread.uniqueId else {
owsFailDebug("threadId was unexpectedly nil")
@ -436,23 +444,26 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
DispatchQueue.main.async {
let sound = self.requestSound(thread: thread)
self.adaptee.notify(category: .errorMessage, body: notificationBody, userInfo: userInfo, sound: sound)
self.adaptee.notify(category: .errorMessage,
title: notificationTitle,
body: notificationBody,
userInfo: userInfo,
sound: sound)
}
}
public func notifyUser(for errorMessage: TSErrorMessage, thread: TSThread, transaction: YapDatabaseReadWriteTransaction) {
let messageText = errorMessage.previewText(with: transaction)
let authorName = thread.name()
let notificationBody: String
let notificationTitle: String?
switch self.previewType {
case .namePreview, .nameNoPreview:
// TODO better format string, seems weird to hardcode ":"
notificationBody = authorName.rtlSafeAppend(":").rtlSafeAppend(" ").rtlSafeAppend(messageText)
notificationTitle = thread.name()
case .noNameNoPreview:
notificationBody = messageText
notificationTitle = nil
}
let notificationBody = errorMessage.previewText(with: transaction)
guard let threadId = thread.uniqueId else {
owsFailDebug("threadId was unexpectedly nil")
return
@ -464,7 +475,11 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
transaction.addCompletionQueue(DispatchQueue.main) {
let sound = self.requestSound(thread: thread)
self.adaptee.notify(category: .errorMessage, body: notificationBody, userInfo: userInfo, sound: sound)
self.adaptee.notify(category: .errorMessage,
title: notificationTitle,
body: notificationBody,
userInfo: userInfo,
sound: sound)
}
}
@ -473,7 +488,11 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
transaction.addCompletionQueue(DispatchQueue.main) {
let sound = self.checkIfShouldPlaySound() ? OWSSounds.globalNotificationSound() : nil
self.adaptee.notify(category: .threadlessErrorMessage, body: notificationBody, userInfo: [:], sound: sound)
self.adaptee.notify(category: .threadlessErrorMessage,
title: nil,
body: notificationBody,
userInfo: [:],
sound: sound)
}
}

View File

@ -137,12 +137,12 @@ extension LegacyNotificationPresenterAdaptee: NotificationPresenterAdaptee {
return promise
}
func notify(category: AppNotificationCategory, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?) {
func notify(category: AppNotificationCategory, title: String?, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?) {
AssertIsOnMainThread()
notify(category: category, body: body, userInfo: userInfo, sound: sound, replacingIdentifier: nil)
notify(category: category, title: title, body: body, userInfo: userInfo, sound: sound, replacingIdentifier: nil)
}
func notify(category: AppNotificationCategory, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?, replacingIdentifier: String?) {
func notify(category: AppNotificationCategory, title: String?, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?, replacingIdentifier: String?) {
AssertIsOnMainThread()
guard UIApplication.shared.applicationState != .active else {
if let sound = sound {
@ -154,9 +154,16 @@ extension LegacyNotificationPresenterAdaptee: NotificationPresenterAdaptee {
return
}
let alertBody: String
if let title = title {
alertBody = title.rtlSafeAppend(":").rtlSafeAppend(" ").rtlSafeAppend(body)
} else {
alertBody = body
}
let notification = UILocalNotification()
notification.category = category.identifier
notification.alertBody = body
notification.alertBody = alertBody
notification.userInfo = userInfo
notification.soundName = sound?.filename

View File

@ -101,12 +101,12 @@ extension UserNotificationPresenterAdaptee: NotificationPresenterAdaptee {
}
}
func notify(category: AppNotificationCategory, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?) {
func notify(category: AppNotificationCategory, title: String?, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?) {
AssertIsOnMainThread()
notify(category: category, body: body, userInfo: userInfo, sound: sound, replacingIdentifier: nil)
notify(category: category, title: title, body: body, userInfo: userInfo, sound: sound, replacingIdentifier: nil)
}
func notify(category: AppNotificationCategory, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?, replacingIdentifier: String?) {
func notify(category: AppNotificationCategory, title: String?, body: String, userInfo: [AnyHashable: Any], sound: OWSSound?, replacingIdentifier: String?) {
AssertIsOnMainThread()
let content = UNMutableNotificationContent()
@ -132,6 +132,9 @@ extension UserNotificationPresenterAdaptee: NotificationPresenterAdaptee {
}
if shouldPresentNotification(category: category, userInfo: userInfo) {
if let title = title {
content.title = title
}
content.body = body
} else {
// Play sound and vibrate, but without a `body` no banner will show.

View File

@ -53,21 +53,12 @@
/* The label for the 'save' button in action sheets. */
"ALERT_SAVE" = "Save";
/* No comment provided by engineer. */
/* notification action */
"ANSWER_CALL_BUTTON_TITLE" = "Answer";
/* No comment provided by engineer. */
/* notification body */
"APN_Message" = "New Message!";
/* No comment provided by engineer. */
"APN_MESSAGE_FROM" = "Message from";
/* No comment provided by engineer. */
"APN_MESSAGE_IN_GROUP" = "Message in group";
/* No comment provided by engineer. */
"APN_MESSAGE_IN_GROUP_DETAILED" = "%@ in group %@: %@";
/* Message for the 'app launch failed' alert. */
"APP_LAUNCH_FAILURE_ALERT_MESSAGE" = "Signal can't launch. Please send a debug log to support@signal.org so that we can troubleshoot this issue.";
@ -329,9 +320,18 @@
/* Alert title when calling and permissions for microphone are missing */
"CALL_AUDIO_PERMISSION_TITLE" = "Microphone Access Required";
/* notification body */
"CALL_INCOMING_NOTIFICATION_BODY" = "☎️ Incoming Call";
/* Accessibility label for placing call button */
"CALL_LABEL" = "Call";
/* notification body */
"CALL_MISSED_BECAUSE_OF_IDENTITY_CHANGE_NOTIFICATION_BODY" = "☎️ Missed call because the caller's safety number changed.";
/* notification body */
"CALL_MISSED_NOTIFICATION_BODY" = "☎️ Missed Call";
/* Call setup status label after outgoing call times out */
"CALL_SCREEN_STATUS_NO_ANSWER" = "No Answer";
@ -1113,16 +1113,13 @@
/* Multi-line label explaining how to show names instead of phone numbers in your inbox */
"INBOX_VIEW_MISSING_CONTACTS_PERMISSION" = "You can enable contacts access in the iOS Settings app to see contact names in your Signal conversation list.";
/* notification body */
/* info message text in conversation view */
"INCOMING_CALL" = "Incoming call";
/* notification body */
"INCOMING_CALL_FROM" = "Incoming call from %@";
/* info message recorded in conversation history when local user declined a call */
"INCOMING_DECLINED_CALL" = "You declined a call";
/* No comment provided by engineer. */
/* info message text in conversation view */
"INCOMING_INCOMPLETE_CALL" = "Incoming call";
/* info message text shown in conversation view */
@ -1374,15 +1371,9 @@
/* Messages that indicates that there are more unseen messages including safety number changes. */
"MESSAGES_VIEW_UNREAD_INDICATOR_HAS_MORE_UNSEEN_MESSAGES_AND_SAFETY_NUMBER_CHANGES" = "There are more unread messages (including safety number changes).";
/* notification title */
/* info message text in conversation view */
"MISSED_CALL" = "Missed call";
/* notification title. Embeds {{caller's name or phone number}} */
"MISSED_CALL_WITH_CHANGED_IDENTITY_BODY_WITH_CALLER_NAME" = "Missed call from %@ because their safety number changed.";
/* notification title */
"MISSED_CALL_WITH_CHANGED_IDENTITY_BODY_WITHOUT_CALLER_NAME" = "Missed call because the caller's safety number changed.";
/* Alert body
Alert body when camera is not authorized */
"MISSING_CAMERA_PERMISSION_MESSAGE" = "You can enable camera access in the iOS Settings app to make video calls in Signal.";
@ -1397,9 +1388,6 @@
/* Alert title when user has previously denied media library access */
"MISSING_MEDIA_LIBRARY_PERMISSION_TITLE" = "Signal requires access to your photos for this feature.";
/* notification title. Embeds {{caller's name or phone number}} */
"MSGVIEW_MISSED_CALL_WITH_NAME" = "Missed call from %@.";
/* alert title: cannot link - reached max linked devices */
"MULTIDEVICE_PAIRING_MAX_DESC" = "You cannot link any more devices.";
@ -1451,6 +1439,9 @@
/* An indicator that a user is a member of the new group. */
"NEW_GROUP_MEMBER_LABEL" = "Member";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ to %@";
/* Placeholder text for group name field */
"NEW_GROUP_NAMEGROUP_REQUEST_DEFAULT" = "Name this group chat";
@ -1481,9 +1472,6 @@
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "You may have received messages while your %@ was restarting.";
/* No comment provided by engineer. */
"NOTIFICATION_SEND_FAILED" = "Your message failed to send to %@.";
/* No comment provided by engineer. */
"NOTIFICATIONS_FOOTER_WARNING" = "Due to known bugs in Apple's push framework, message previews will only be shown if the message is retrieved within 30 seconds after being sent. The application badge might be inaccurate as a result.";
@ -1520,10 +1508,10 @@
/* Label warning the user that the Signal service may be down. */
"OUTAGE_WARNING" = "Signal is experiencing technical difficulties. We are working hard to restore service as quickly as possible.";
/* No comment provided by engineer. */
/* info message text in conversation view */
"OUTGOING_CALL" = "Outgoing call";
/* No comment provided by engineer. */
/* info message text in conversation view */
"OUTGOING_INCOMPLETE_CALL" = "Outgoing call";
/* info message recorded in conversation history when local user tries and fails to call another user. */
@ -1667,10 +1655,10 @@
/* Title for the profile view. */
"PROFILE_VIEW_TITLE" = "Profile";
/* No comment provided by engineer. */
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "Mark as Read";
/* No comment provided by engineer. */
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "Reply";
/* Title of alert shown when push tokens sync job succeeds. */
@ -1814,7 +1802,7 @@
/* Title of alert indicating that users needs to enter a phone number to register. */
"REGISTRATION_VIEW_NO_PHONE_NUMBER_ALERT_TITLE" = "No Phone Number";
/* No comment provided by engineer. */
/* notification action */
"REJECT_CALL_BUTTON_TITLE" = "Reject";
/* No comment provided by engineer. */
@ -1922,9 +1910,12 @@
/* No comment provided by engineer. */
"SEND_AGAIN_BUTTON" = "Send Again";
/* Label for the send button in the conversation view. */
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
/* Alert body after invite failed */
"SEND_INVITE_FAILURE" = "Sending invite failed, please try again later.";

View File

@ -50,8 +50,7 @@ public class MessageApprovalViewController: OWSViewController, UITextViewDelegat
comment: "Title for the 'message approval' dialog.")
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(cancelPressed))
sendButton = UIBarButtonItem(title: NSLocalizedString("SEND_BUTTON_TITLE",
comment: "Label for the send button in the conversation view."),
sendButton = UIBarButtonItem(title: MessageStrings.sendButton,
style: .plain,
target: self,
action: #selector(sendPressed))

View File

@ -37,6 +37,27 @@ import Foundation
static public let sendButton = NSLocalizedString("SEND_BUTTON_TITLE", comment: "Label for the button to send a message")
}
@objc
public class NotificationStrings: NSObject {
@objc
static public let incomingCallBody = NSLocalizedString("CALL_INCOMING_NOTIFICATION_BODY", comment: "notification body")
@objc
static public let missedCallBody = NSLocalizedString("CALL_MISSED_NOTIFICATION_BODY", comment: "notification body")
@objc
static public let missedCallBecauseOfIdentityChangeBody = NSLocalizedString("CALL_MISSED_BECAUSE_OF_IDENTITY_CHANGE_NOTIFICATION_BODY", comment: "notification body")
@objc
static public let incomingMessageBody = NSLocalizedString("APN_Message", comment: "notification body")
@objc
static public let incomingGroupMessageTitleFormat = NSLocalizedString("NEW_GROUP_MESSAGE_NOTIFICATION_TITLE", comment: "notification title. Embeds {{author name}} and {{group name}}")
@objc
static public let failedToSendBody = NSLocalizedString("SEND_FAILED_NOTIFICATION_BODY", comment: "notification body")
}
@objc public class CallStrings: NSObject {
@objc
static public let callStatusFormat = NSLocalizedString("CALL_STATUS_FORMAT", comment: "embeds {{Call Status}} in call screen label. For ongoing calls, {{Call Status}} is a seconds timer like 01:23, otherwise {{Call Status}} is a short text like 'Ringing', 'Busy', or 'Failed Call'")
@ -59,25 +80,7 @@ import Foundation
@objc
static public let answerCallButtonTitle = NSLocalizedString("ANSWER_CALL_BUTTON_TITLE", comment: "notification action")
@objc
static public let declineCallButtonTitle = NSLocalizedString("REJECT_CALL_BUTTON_TITLE", comment: "")
// MARK: Missed Call Notification
@objc
static public let missedCallNotificationBodyWithoutCallerName = NSLocalizedString("MISSED_CALL", comment: "notification title")
@objc
static public let missedCallNotificationBodyWithCallerName = NSLocalizedString("MSGVIEW_MISSED_CALL_WITH_NAME", comment: "notification title. Embeds {{caller's name or phone number}}")
// MARK: Missed with changed identity notification (for not previously verified identity)
@objc
static public let missedCallWithIdentityChangeNotificationBodyWithoutCallerName = NSLocalizedString("MISSED_CALL_WITH_CHANGED_IDENTITY_BODY_WITHOUT_CALLER_NAME", comment: "notification title")
@objc
static public let missedCallWithIdentityChangeNotificationBodyWithCallerName = NSLocalizedString("MISSED_CALL_WITH_CHANGED_IDENTITY_BODY_WITH_CALLER_NAME", comment: "notification title. Embeds {{caller's name or phone number}}")
@objc
static public let incomingCallWithoutCallerNameNotification = NSLocalizedString("INCOMING_CALL", comment: "notification body, does not include the callers name")
@objc
static public let incomingCallNotificationFormat = NSLocalizedString("INCOMING_CALL_FROM", comment: "notification body, embeds {{caller name or number}}")
static public let declineCallButtonTitle = NSLocalizedString("REJECT_CALL_BUTTON_TITLE", comment: "notification action")
}
@objc public class MediaStrings: NSObject {

View File

@ -98,15 +98,15 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
// We don't actually use the `transaction` but other sibling classes do.
switch (_callType) {
case RPRecentCallTypeIncoming:
return NSLocalizedString(@"INCOMING_CALL", @"");
return NSLocalizedString(@"INCOMING_CALL", @"info message text in conversation view");
case RPRecentCallTypeOutgoing:
return NSLocalizedString(@"OUTGOING_CALL", @"");
return NSLocalizedString(@"OUTGOING_CALL", @"info message text in conversation view");
case RPRecentCallTypeIncomingMissed:
return NSLocalizedString(@"MISSED_CALL", @"");
return NSLocalizedString(@"MISSED_CALL", @"info message text in conversation view");
case RPRecentCallTypeOutgoingIncomplete:
return NSLocalizedString(@"OUTGOING_INCOMPLETE_CALL", @"");
return NSLocalizedString(@"OUTGOING_INCOMPLETE_CALL", @"info message text in conversation view");
case RPRecentCallTypeIncomingIncomplete:
return NSLocalizedString(@"INCOMING_INCOMPLETE_CALL", @"");
return NSLocalizedString(@"INCOMING_INCOMPLETE_CALL", @"info message text in conversation view");
case RPRecentCallTypeIncomingMissedBecauseOfChangedIdentity:
return NSLocalizedString(@"INFO_MESSAGE_MISSED_CALL_DUE_TO_CHANGED_IDENITY", @"info message text shown in conversation view");
case RPRecentCallTypeIncomingDeclined: