Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public void onReceived() {

private void handleNotification() {
Ejson receivedEjson = safeFromJson(mBundle.getString("ejson", "{}"), Ejson.class);

if (receivedEjson != null && receivedEjson.notificationType != null && receivedEjson.notificationType.equals("message-id-only")) {
Log.d(TAG, "Detected message-id-only notification, will fetch full content from server");
loadNotificationAndProcess(receivedEjson);
Expand Down Expand Up @@ -202,8 +202,12 @@ private void showNotification(Bundle bundle, Ejson ejson, String notId) {
boolean hasSender = ejson != null && ejson.sender != null;
String title = bundle.getString("title");

String displaySenderName = (ejson != null && ejson.senderName != null && !ejson.senderName.isEmpty())
? ejson.senderName
: (hasSender ? ejson.sender.username : title);

bundle.putLong("time", new Date().getTime());
bundle.putString("username", hasSender ? ejson.sender.username : title);
bundle.putString("username", displaySenderName);
bundle.putString("senderId", hasSender ? ejson.sender._id : "1");

String avatarUri = ejson != null ? ejson.getAvatarUri() : null;
Expand Down Expand Up @@ -291,19 +295,6 @@ private Notification.Builder buildNotification(int notificationId) {

// Determine the correct title based on notification type
String notificationTitle = title;
if (ejson != null && ejson.type != null) {
if ("p".equals(ejson.type) || "c".equals(ejson.type)) {
// For groups/channels, use room name if available, otherwise fall back to title
notificationTitle = (ejson.name != null && !ejson.name.isEmpty()) ? ejson.name : title;
} else if ("d".equals(ejson.type)) {
// For direct messages, use title (sender name from server)
notificationTitle = title;
} else if ("l".equals(ejson.type)) {
// For omnichannel, use sender name if available, otherwise fall back to title
notificationTitle = (ejson.sender != null && ejson.sender.name != null && !ejson.sender.name.isEmpty())
? ejson.sender.name : title;
}
}

if (ENABLE_VERBOSE_LOGS) {
Log.d(TAG, "[buildNotification] notId=" + notId);
Expand Down Expand Up @@ -465,19 +456,6 @@ private void notificationStyle(Notification.Builder notification, int notId, Bun
// Determine the correct conversation title based on notification type
Ejson bundleEjson = safeFromJson(bundle.getString("ejson", "{}"), Ejson.class);
String conversationTitle = title;
if (bundleEjson != null && bundleEjson.type != null) {
if ("p".equals(bundleEjson.type) || "c".equals(bundleEjson.type)) {
// For groups/channels, use room name if available, otherwise fall back to title
conversationTitle = (bundleEjson.name != null && !bundleEjson.name.isEmpty()) ? bundleEjson.name : title;
} else if ("d".equals(bundleEjson.type)) {
// For direct messages, use title (sender name from server)
conversationTitle = title;
} else if ("l".equals(bundleEjson.type)) {
// For omnichannel, use sender name if available, otherwise fall back to title
conversationTitle = (bundleEjson.sender != null && bundleEjson.sender.name != null && !bundleEjson.sender.name.isEmpty())
? bundleEjson.sender.name : title;
}
}
messageStyle.setConversationTitle(conversationTitle);

if (bundles != null) {
Expand All @@ -489,15 +467,17 @@ private void notificationStyle(Notification.Builder notification, int notId, Bun
Ejson ejson = safeFromJson(data.getString("ejson", "{}"), Ejson.class);
String m = extractMessage(message, ejson);

String displaySenderName = (ejson != null && ejson.senderName != null && !ejson.senderName.isEmpty())
? ejson.senderName
: (ejson != null && ejson.sender != null ? ejson.sender.username : title);

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
String senderName = ejson != null ? ejson.senderName : "Unknown";
messageStyle.addMessage(m, timestamp, senderName);
messageStyle.addMessage(m, timestamp, displaySenderName);
} else {
Bitmap avatar = getAvatar(avatarUri);
String senderName = ejson != null ? ejson.senderName : "Unknown";
Person.Builder senderBuilder = new Person.Builder()
.setKey(senderId)
.setName(senderName);
.setName(displaySenderName);

if (avatar != null) {
senderBuilder.setIcon(Icon.createWithBitmap(avatar));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,18 @@ private String buildAvatarUri(String avatarPath, String errorContext) {
String userToken = token();
String uid = userId();

if (userToken.isEmpty() || uid.isEmpty()) {
Log.w(TAG, "Cannot generate " + errorContext + " avatar URI: missing auth credentials");
return null;
String finalUri = server + avatarPath + "?format=png&size=100";
if (!userToken.isEmpty() && !uid.isEmpty()) {
finalUri += "&rc_token=" + userToken + "&rc_uid=" + uid;
}

return server + avatarPath + "?format=png&size=100&rc_token=" + userToken + "&rc_uid=" + uid;
return finalUri;
}

public String getAvatarUri() {
String avatarPath;

// For DMs, show sender's avatar; for groups/channels, show room avatar
if ("d".equals(type)) {
// Direct message: use sender's avatar
if (sender == null || sender.username == null || sender.username.isEmpty()) {
Log.w(TAG, "Cannot generate avatar URI: sender or username is null");
return null;
Expand All @@ -92,7 +90,6 @@ public String getAvatarUri() {
return null;
}
} else {
// Group/Channel/Livechat: use room avatar
if (rid == null || rid.isEmpty()) {
Log.w(TAG, "Cannot generate avatar URI: rid is null for non-DM");
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ class VideoConfNotification(private val context: Context) {

if (ejson.caller != null) {
callerId = ejson.caller._id ?: ""
callerName = ejson.caller.name ?: "Unknown"
callerName = ejson.senderName ?: ejson.caller.name ?: "Unknown"
} else if (ejson.sender != null) {
// Fallback to sender if caller is not present
callerId = ejson.sender._id ?: ""
callerName = ejson.sender.name ?: ejson.senderName ?: "Unknown"
callerName = ejson.senderName ?: ejson.sender.name ?: "Unknown"
} else {
callerId = ""
callerName = "Unknown"
Expand Down
45 changes: 22 additions & 23 deletions ios/NotificationService/NotificationService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,21 @@ class NotificationService: UNNotificationServiceExtension {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

guard let bestAttemptContent = bestAttemptContent,
let ejsonString = bestAttemptContent.userInfo["ejson"] as? String,
let ejson = ejsonString.data(using: .utf8),
let payload = try? JSONDecoder().decode(Payload.self, from: ejson) else {
contentHandler(request.content)
return
}

rocketchat = RocketChat(server: payload.host.removeTrailingSlash())

if payload.notificationType == .videoconf {
processVideoConf(payload: payload)
} else if payload.notificationType == .messageIdOnly {
fetchMessageContent(payload: payload)
if let bestAttemptContent = bestAttemptContent,
let ejsonString = bestAttemptContent.userInfo["ejson"] as? String,
let ejson = ejsonString.data(using: .utf8),
let payload = try? JSONDecoder().decode(Payload.self, from: ejson) {
rocketchat = RocketChat(server: payload.host.removeTrailingSlash())

if payload.notificationType == .videoconf {
processVideoConf(payload: payload)
} else if payload.notificationType == .messageIdOnly {
fetchMessageContent(payload: payload)
} else {
processPayload(payload: payload)
}
} else {
processPayload(payload: payload)
contentHandler(request.content)
}
}

Expand All @@ -49,7 +48,7 @@ class NotificationService: UNNotificationServiceExtension {
}

// 1. Setup Basic Content
let callerName = payload.caller?.name ?? "Unknown"
let callerName = payload.senderName ?? payload.caller?.name ?? "Unknown"
bestAttemptContent.title = NSLocalizedString("Video Call", comment: "")
bestAttemptContent.body = String(format: NSLocalizedString("Incoming call from %@", comment: ""), callerName)
bestAttemptContent.categoryIdentifier = "VIDEOCONF"
Expand Down Expand Up @@ -77,14 +76,15 @@ class NotificationService: UNNotificationServiceExtension {
guard let bestAttemptContent = bestAttemptContent else { return }

// 1. Setup Basic Content (Title/Body)
let senderName = payload.sender?.name ?? payload.senderName ?? "Unknown"
let senderName = payload.senderName ?? payload.sender?.name ?? "Unknown"
let senderUsername = payload.sender?.username ?? payload.senderName ?? ""

bestAttemptContent.title = senderName
if bestAttemptContent.title.isEmpty {
bestAttemptContent.title = senderName
}

if let roomType = payload.type {
if roomType == .group || roomType == .channel {
bestAttemptContent.title = payload.name ?? senderName
// Strip sender prefix if present
if let body = bestAttemptContent.body as? String {
let prefix = "\(senderUsername): "
Expand All @@ -98,8 +98,6 @@ class NotificationService: UNNotificationServiceExtension {
}
}
}
} else if roomType == .livechat {
bestAttemptContent.title = payload.sender?.name ?? senderName
}
}

Expand All @@ -122,7 +120,7 @@ class NotificationService: UNNotificationServiceExtension {
avatarData: avatarData,
conversationId: payload.rid ?? "",
isGroup: isGroup,
groupName: payload.name
groupName: bestAttemptContent.title
)

self.contentHandler?(self.finalContent ?? bestAttemptContent)
Expand Down Expand Up @@ -214,7 +212,8 @@ class NotificationService: UNNotificationServiceExtension {
if let messageId = payload.messageId {
self.rocketchat?.getPushWithId(messageId) { notification in
if let notification = notification {
// Set body first, processPayload will strip sender prefix for groups/channels
// Set title and body first, processPayload will strip sender prefix for groups/channels
self.bestAttemptContent?.title = notification.title
self.bestAttemptContent?.body = notification.text

// Update ejson with full payload from server for correct navigation
Expand Down
Loading