diff --git a/zerver/lib/push_notifications.py b/zerver/lib/push_notifications.py index 3d3648547f..dc03656968 100644 --- a/zerver/lib/push_notifications.py +++ b/zerver/lib/push_notifications.py @@ -47,6 +47,7 @@ from zerver.lib.remote_server import ( from zerver.lib.soft_deactivation import soft_reactivate_if_personal_notification from zerver.lib.tex import change_katex_to_raw_latex from zerver.lib.timestamp import datetime_to_timestamp +from zerver.lib.topic import get_topic_display_name from zerver.lib.url_decoding import is_same_server_message_link from zerver.lib.users import check_can_access_user from zerver.models import ( @@ -992,7 +993,7 @@ def get_message_payload( data["recipient_type"] = "stream" data["stream"] = get_message_stream_name_from_database(message) data["stream_id"] = message.recipient.type_id - data["topic"] = message.topic_name() + data["topic"] = get_topic_display_name(message.topic_name(), user_profile.default_language) elif message.recipient.type == Recipient.DIRECT_MESSAGE_GROUP: data["recipient_type"] = "private" data["pm_users"] = direct_message_group_users(message.recipient.id) @@ -1002,7 +1003,7 @@ def get_message_payload( return data -def get_apns_alert_title(message: Message) -> str: +def get_apns_alert_title(message: Message, language: str) -> str: """ On an iOS notification, this is the first bolded line. """ @@ -1012,7 +1013,8 @@ def get_apns_alert_title(message: Message) -> str: return ", ".join(sorted(r["full_name"] for r in recipients)) elif message.is_stream_message(): stream_name = get_message_stream_name_from_database(message) - return f"#{stream_name} > {message.topic_name()}" + topic_display_name = get_topic_display_name(message.topic_name(), language) + return f"#{stream_name} > {topic_display_name}" # For 1:1 direct messages, we just show the sender name. return message.sender.full_name @@ -1105,7 +1107,7 @@ def get_message_payload_apns( content, _ = truncate_content(get_mobile_push_content(message.rendered_content)) apns_data = { "alert": { - "title": get_apns_alert_title(message), + "title": get_apns_alert_title(message, user_profile.default_language), "subtitle": get_apns_alert_subtitle( message, trigger, user_profile, mentioned_user_group_name, can_access_sender ), diff --git a/zerver/tests/test_push_notifications.py b/zerver/tests/test_push_notifications.py index 377468770d..2409b63633 100644 --- a/zerver/tests/test_push_notifications.py +++ b/zerver/tests/test_push_notifications.py @@ -4196,13 +4196,21 @@ class TestGetAPNsPayload(PushNotificationTest): self.assertDictEqual(payload, expected) mock_push_notifications.assert_called() - def _test_get_message_payload_apns_stream_message(self, trigger: str) -> None: + def _test_get_message_payload_apns_stream_message( + self, trigger: str, empty_string_topic: bool = False + ) -> None: stream = Stream.objects.filter(name="Verona").get() message = self.get_message(Recipient.STREAM, stream.id, stream.realm_id) + topic_display_name = message.topic_name() + if empty_string_topic: + message.set_topic_name("") + message.save() + topic_display_name = Message.EMPTY_TOPIC_FALLBACK_NAME + payload = get_message_payload_apns(self.sender, message, trigger) expected = { "alert": { - "title": "#Verona > Test topic", + "title": f"#Verona > {topic_display_name}", "subtitle": "King Hamlet:", "body": message.content, }, @@ -4216,7 +4224,7 @@ class TestGetAPNsPayload(PushNotificationTest): "sender_id": self.sender.id, "stream": stream.name, "stream_id": stream.id, - "topic": message.topic_name(), + "topic": topic_display_name, "server": settings.EXTERNAL_HOST, "realm_id": self.sender.realm.id, "realm_name": self.sender.realm.name, @@ -4235,6 +4243,11 @@ class TestGetAPNsPayload(PushNotificationTest): def test_get_message_payload_apns_followed_topic_message(self) -> None: self._test_get_message_payload_apns_stream_message(NotificationTriggers.FOLLOWED_TOPIC_PUSH) + def test_get_message_payload_apns_empty_string_topic(self) -> None: + self._test_get_message_payload_apns_stream_message( + NotificationTriggers.STREAM_PUSH, empty_string_topic=True + ) + def test_get_message_payload_apns_stream_mention(self) -> None: user_profile = self.example_user("othello") stream = Stream.objects.filter(name="Verona").get() @@ -4469,9 +4482,11 @@ class TestGetGCMPayload(PushNotificationTest): truncate_content: bool = False, mentioned_user_group_id: int | None = None, mentioned_user_group_name: str | None = None, + empty_string_topic: bool = False, ) -> None: stream = Stream.objects.filter(name="Verona").get() message = self.get_message(Recipient.STREAM, stream.id, stream.realm_id) + content = message.content if truncate_content: message.content = "a" * 210 @@ -4479,6 +4494,12 @@ class TestGetGCMPayload(PushNotificationTest): message.save() content = "a" * 200 + "…" + topic_display_name = message.topic_name() + if empty_string_topic: + message.set_topic_name("") + message.save() + topic_display_name = Message.EMPTY_TOPIC_FALLBACK_NAME + hamlet = self.example_user("hamlet") payload, gcm_options = get_message_payload_gcm( hamlet, message, mentioned_user_group_id, mentioned_user_group_name @@ -4502,7 +4523,7 @@ class TestGetGCMPayload(PushNotificationTest): "recipient_type": "stream", "stream": stream.name, "stream_id": stream.id, - "topic": message.topic_name(), + "topic": topic_display_name, } if mentioned_user_group_id is not None: @@ -4533,6 +4554,9 @@ class TestGetGCMPayload(PushNotificationTest): mentioned_user_group_name="mobile_team", ) + def test_get_message_payload_gcm_empty_string_topic(self) -> None: + self._test_get_message_payload_gcm_stream_message(empty_string_topic=True) + def test_get_message_payload_gcm_direct_message(self) -> None: message = self.get_message( Recipient.PERSONAL,