diff --git a/go/bind/keybase.go b/go/bind/keybase.go index 46a59821568..c5bd8f3acee 100644 --- a/go/bind/keybase.go +++ b/go/bind/keybase.go @@ -70,7 +70,7 @@ func log(format string, args ...interface{}) { } type PushNotifier interface { - LocalNotification(ident string, msg string, badgeCount int, soundName string, convID string, typ string) + LocalNotification(ident string, title string, msg string, badgeCount int, soundName string, convID string, typ string) DisplayChatNotification(notification *ChatNotification) } @@ -688,7 +688,7 @@ func pushPendingMessageFailure(obrs []chat1.OutboxRecord, pusher PushNotifier) { for _, obr := range obrs { if topicType := obr.Msg.ClientHeader.Conv.TopicType; obr.Msg.IsBadgableType() && topicType == chat1.TopicType_CHAT { kbCtx.Log.Debug("pushPendingMessageFailure: pushing convID: %s", obr.ConvID) - pusher.LocalNotification("failedpending", + pusher.LocalNotification("failedpending", "", "Heads up! Your message hasn't sent yet, tap here to retry.", -1, "default", obr.ConvID.String(), "chat.failedpending") return diff --git a/go/bind/notifications.go b/go/bind/notifications.go index 5ce690763a4..48aa41f494e 100644 --- a/go/bind/notifications.go +++ b/go/bind/notifications.go @@ -26,8 +26,27 @@ import ( var ( seenNotificationsMtx sync.Mutex seenNotifications, _ = lru.New(100) + + multipleAccountsMtx sync.Mutex + multipleAccountsCached *bool ) +func hasMultipleLoggedInAccounts(ctx context.Context) bool { + multipleAccountsMtx.Lock() + defer multipleAccountsMtx.Unlock() + if multipleAccountsCached != nil { + return *multipleAccountsCached + } + users, err := kbCtx.GetUsersWithStoredSecrets(ctx) + if err != nil { + // Don't cache on error; retry next time. + return false + } + result := len(users) > 1 + multipleAccountsCached = &result + return result +} + type Person struct { KeybaseUsername string KeybaseAvatar string @@ -55,6 +74,8 @@ type ChatNotification struct { IsPlaintext bool SoundName string BadgeCount int + // Title is the notification title, e.g. "username@keybase" + Title string } func HandlePostTextReply(strConvID, tlfName string, intMessageID int, body string) (err error) { @@ -144,6 +165,11 @@ func HandleBackgroundNotification(strConvID, body, serverMessageBody, sender str return err } + currentUsername := string(kbCtx.Env.GetUsername()) + title := "Keybase" + if hasMultipleLoggedInAccounts(ctx) { + title = fmt.Sprintf("%s@keybase", currentUsername) + } chatNotification := ChatNotification{ IsPlaintext: displayPlaintext, Message: &Message{ @@ -156,10 +182,12 @@ func HandleBackgroundNotification(strConvID, body, serverMessageBody, sender str TopicName: conv.Info.TopicName, TlfName: conv.Info.TlfName, IsGroupConversation: len(conv.Info.Participants) > 2, - ConversationName: utils.FormatConversationName(conv.Info, string(kbCtx.Env.GetUsername())), + ConversationName: utils.FormatConversationName(conv.Info, currentUsername), SoundName: soundName, BadgeCount: badgeCount, + Title: title, } + kbCtx.Log.CDebugf(ctx, "HandleBackgroundNotification: title=%s", chatNotification.Title) msgUnboxed, err := mp.UnboxPushNotification(ctx, uid, convID, membersType, body) if err == nil && msgUnboxed.IsValid() { diff --git a/shared/android/app/src/main/java/io/keybase/ossifrage/KBPushNotifier.kt b/shared/android/app/src/main/java/io/keybase/ossifrage/KBPushNotifier.kt index 2d071a144bf..b3c8f2a4d9f 100644 --- a/shared/android/app/src/main/java/io/keybase/ossifrage/KBPushNotifier.kt +++ b/shared/android/app/src/main/java/io/keybase/ossifrage/KBPushNotifier.kt @@ -122,6 +122,7 @@ class KBPushNotifier internal constructor(private val context: Context, private val convData = ConvData(chatNotification.convID, chatNotification.tlfName ?: "", chatNotification.message.id) val builder = NotificationCompat.Builder(context, KeybasePushNotificationListenerService.CHAT_CHANNEL_ID) .setSmallIcon(R.drawable.ic_notif) + .setContentTitle(chatNotification.title ?: "") .setContentIntent(pending_intent) .setAutoCancel(true) var notificationDefaults = NotificationCompat.DEFAULT_LIGHTS or NotificationCompat.DEFAULT_VIBRATE @@ -228,9 +229,9 @@ class KBPushNotifier internal constructor(private val context: Context, private notificationManager.notify(uniqueTag, 0, builder.build()) } - override fun localNotification(ident: String, msg: String, badgeCount: Long, soundName: String, convID: String, + override fun localNotification(ident: String, title: String, msg: String, badgeCount: Long, soundName: String, convID: String, typ: String) { - genericNotification(ident, "", msg, bundle, KeybasePushNotificationListenerService.GENERAL_CHANNEL_ID) + genericNotification(ident, title, msg, bundle, KeybasePushNotificationListenerService.GENERAL_CHANNEL_ID) } companion object { diff --git a/shared/ios/Keybase/Pusher.swift b/shared/ios/Keybase/Pusher.swift index 75650447a74..d6c6b84ff37 100644 --- a/shared/ios/Keybase/Pusher.swift +++ b/shared/ios/Keybase/Pusher.swift @@ -1,17 +1,22 @@ import Foundation -import UserNotifications import Keybasego +import UserNotifications class PushNotifier: NSObject, Keybasego.KeybasePushNotifierProtocol { - func localNotification(_ ident: String?, msg: String?, badgeCount: Int, soundName: String?, convID: String?, typ: String?) { + func localNotification( + _ ident: String?, title: String?, msg: String?, badgeCount: Int, soundName: String?, + convID: String?, typ: String? + ) { let content = UNMutableNotificationContent() if let soundName = soundName { content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: soundName)) } content.badge = (badgeCount >= 0) ? NSNumber(value: badgeCount) : nil + content.title = title ?? "" content.body = msg ?? "" content.userInfo = ["convID": convID ?? "", "type": typ ?? ""] - let request = UNNotificationRequest(identifier: ident ?? UUID().uuidString, content: content, trigger: nil) + let request = UNNotificationRequest( + identifier: ident ?? UUID().uuidString, content: content, trigger: nil) UNUserNotificationCenter.current().add(request) { error in if let error = error { NSLog("local notification failed: %@", error.localizedDescription) @@ -27,12 +32,17 @@ class PushNotifier: NSObject, Keybasego.KeybasePushNotifierProtocol { if notification.isPlaintext && !message.plaintext.isEmpty { let username = message.from?.keybaseUsername ?? "" let convName = notification.conversationName - msg = (username == convName || convName.isEmpty) + msg = + (username == convName || convName.isEmpty) ? "\(username): \(message.plaintext)" : "\(username) (\(convName)): \(message.plaintext)" } else { msg = message.serverMessage } - localNotification(ident, msg: msg, badgeCount: notification.badgeCount, soundName: notification.soundName, convID: notification.convID, typ: "chat.newmessage") + let title = notification.title + NSLog("PushNotifier display: title=%@", title ?? "") + localNotification( + ident, title: title, msg: msg, badgeCount: notification.badgeCount, + soundName: notification.soundName, convID: notification.convID, typ: "chat.newmessage") } }