From d88ffc4775d4ce429728e776b3902dd3258c2287 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 30 Jan 2019 19:11:56 -0700 Subject: [PATCH 1/2] Notification titles for iOS10+ --- .../Notifications/AppNotifications.swift | 127 ++++++++++-------- .../LegacyNotificationsAdaptee.swift | 15 ++- .../UserNotificationsAdaptee.swift | 9 +- .../translations/en.lproj/Localizable.strings | 61 ++++----- .../MessageApprovalViewController.swift | 3 +- SignalMessaging/Views/CommonStrings.swift | 41 +++--- SignalServiceKit/src/Messages/TSCall.m | 10 +- 7 files changed, 144 insertions(+), 122 deletions(-) diff --git a/Signal/src/UserInterface/Notifications/AppNotifications.swift b/Signal/src/UserInterface/Notifications/AppNotifications.swift index eb804a629..6983087df 100644 --- a/Signal/src/UserInterface/Notifications/AppNotifications.swift +++ b/Signal/src/UserInterface/Notifications/AppNotifications.swift @@ -115,8 +115,8 @@ protocol NotificationPresenterAdaptee: class { func registerNotificationSettings() -> Promise - 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) } } diff --git a/Signal/src/UserInterface/Notifications/LegacyNotificationsAdaptee.swift b/Signal/src/UserInterface/Notifications/LegacyNotificationsAdaptee.swift index 0d66667d6..9b2bb4429 100644 --- a/Signal/src/UserInterface/Notifications/LegacyNotificationsAdaptee.swift +++ b/Signal/src/UserInterface/Notifications/LegacyNotificationsAdaptee.swift @@ -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 diff --git a/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift b/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift index e49f20f8b..b9f1cddbf 100644 --- a/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift +++ b/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift @@ -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. diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index d72118f0c..ef6fbda3c 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -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."; diff --git a/SignalMessaging/ViewControllers/MessageApprovalViewController.swift b/SignalMessaging/ViewControllers/MessageApprovalViewController.swift index f836f3568..c63f905e5 100644 --- a/SignalMessaging/ViewControllers/MessageApprovalViewController.swift +++ b/SignalMessaging/ViewControllers/MessageApprovalViewController.swift @@ -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)) diff --git a/SignalMessaging/Views/CommonStrings.swift b/SignalMessaging/Views/CommonStrings.swift index 8acba7c43..a5e4649d3 100644 --- a/SignalMessaging/Views/CommonStrings.swift +++ b/SignalMessaging/Views/CommonStrings.swift @@ -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 { diff --git a/SignalServiceKit/src/Messages/TSCall.m b/SignalServiceKit/src/Messages/TSCall.m index a32ee627c..67c6fcc98 100644 --- a/SignalServiceKit/src/Messages/TSCall.m +++ b/SignalServiceKit/src/Messages/TSCall.m @@ -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: From fe4e416dafa3e1611ca921559d5d0b0a26e312a9 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 4 Feb 2019 10:40:55 -0700 Subject: [PATCH 2/2] filter notification text --- .../Notifications/LegacyNotificationsAdaptee.swift | 3 ++- .../Notifications/UserNotificationsAdaptee.swift | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Signal/src/UserInterface/Notifications/LegacyNotificationsAdaptee.swift b/Signal/src/UserInterface/Notifications/LegacyNotificationsAdaptee.swift index 9b2bb4429..5ec257521 100644 --- a/Signal/src/UserInterface/Notifications/LegacyNotificationsAdaptee.swift +++ b/Signal/src/UserInterface/Notifications/LegacyNotificationsAdaptee.swift @@ -156,6 +156,7 @@ extension LegacyNotificationPresenterAdaptee: NotificationPresenterAdaptee { let alertBody: String if let title = title { + // TODO - Make this a format string for better l10n alertBody = title.rtlSafeAppend(":").rtlSafeAppend(" ").rtlSafeAppend(body) } else { alertBody = body @@ -163,7 +164,7 @@ extension LegacyNotificationPresenterAdaptee: NotificationPresenterAdaptee { let notification = UILocalNotification() notification.category = category.identifier - notification.alertBody = alertBody + notification.alertBody = alertBody.filterForDisplay notification.userInfo = userInfo notification.soundName = sound?.filename diff --git a/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift b/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift index b9f1cddbf..6b037c8aa 100644 --- a/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift +++ b/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift @@ -132,10 +132,12 @@ extension UserNotificationPresenterAdaptee: NotificationPresenterAdaptee { } if shouldPresentNotification(category: category, userInfo: userInfo) { - if let title = title { - content.title = title + if let displayableTitle = title?.filterForDisplay { + content.title = displayableTitle + } + if let displayableBody = body.filterForDisplay { + content.body = displayableBody } - content.body = body } else { // Play sound and vibrate, but without a `body` no banner will show. Logger.debug("supressing notification body")