diff --git a/zerver/lib/events.py b/zerver/lib/events.py index 508d708d8c..bb9940dc5e 100644 --- a/zerver/lib/events.py +++ b/zerver/lib/events.py @@ -1092,6 +1092,7 @@ def do_events_register( user_avatar_url_field_optional = client_capabilities.get( "user_avatar_url_field_optional", False ) + stream_typing_notifications = client_capabilities.get("stream_typing_notifications", False) if user_profile.realm.email_address_visibility != Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE: # If real email addresses are not available to the user, their @@ -1111,6 +1112,7 @@ def do_events_register( all_public_streams, narrow=narrow, bulk_message_deletion=bulk_message_deletion, + stream_typing_notifications=stream_typing_notifications, ) if queue_id is None: diff --git a/zerver/lib/home.py b/zerver/lib/home.py index 6d742ef48b..8ae00b54fa 100644 --- a/zerver/lib/home.py +++ b/zerver/lib/home.py @@ -162,6 +162,7 @@ def build_page_params_for_home_page_load( "notification_settings_null": True, "bulk_message_deletion": True, "user_avatar_url_field_optional": True, + "stream_typing_notifications": False, # Set this to True when frontend support is implemented. } if user_profile is not None: diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index 93253565f1..e4ce908d9a 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -6885,6 +6885,9 @@ paths: to optimize network performance. This is an important optimization in organizations with 10,000s of users. New in Zulip 3.0 (feature level 18). + + * `stream_typing_notifications`: Boolean for whether the client + supports stream typing notifications. content: application/json: schema: diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index a8d0edef1c..78c87b48a5 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -227,6 +227,7 @@ class BaseAction(ZulipTestCase): include_streams: bool = True, num_events: int = 1, bulk_message_deletion: bool = True, + stream_typing_notifications: bool = True, ) -> List[Dict[str, Any]]: """ Make sure we have a clean slate of client descriptors for these tests. @@ -252,6 +253,7 @@ class BaseAction(ZulipTestCase): last_connection_time=time.time(), narrow=[], bulk_message_deletion=bulk_message_deletion, + stream_typing_notifications=stream_typing_notifications, ) ) diff --git a/zerver/tornado/django_api.py b/zerver/tornado/django_api.py index 00e1915212..c4e56fb4b5 100644 --- a/zerver/tornado/django_api.py +++ b/zerver/tornado/django_api.py @@ -74,6 +74,7 @@ def request_event_queue( all_public_streams: bool = False, narrow: Iterable[Sequence[str]] = [], bulk_message_deletion: bool = False, + stream_typing_notifications: bool = False, ) -> Optional[str]: if not settings.USING_TORNADO: @@ -93,6 +94,7 @@ def request_event_queue( "secret": settings.SHARED_SECRET, "lifespan_secs": queue_lifespan_secs, "bulk_message_deletion": orjson.dumps(bulk_message_deletion), + "stream_typing_notifications": orjson.dumps(stream_typing_notifications), } if event_types is not None: diff --git a/zerver/tornado/event_queue.py b/zerver/tornado/event_queue.py index 4f6bc06dfe..0fbf9701a3 100644 --- a/zerver/tornado/event_queue.py +++ b/zerver/tornado/event_queue.py @@ -86,6 +86,7 @@ class ClientDescriptor: lifespan_secs: int = 0, narrow: Iterable[Sequence[str]] = [], bulk_message_deletion: bool = False, + stream_typing_notifications: bool = False, ) -> None: # These objects are serialized on shutdown and restored on restart. # If fields are added or semantics are changed, temporary code must be @@ -107,6 +108,7 @@ class ClientDescriptor: self.narrow = narrow self.narrow_filter = build_narrow_filter(narrow) self.bulk_message_deletion = bulk_message_deletion + self.stream_typing_notifications = stream_typing_notifications # Default for lifespan_secs is DEFAULT_EVENT_QUEUE_TIMEOUT_SECS; # but users can set it as high as MAX_QUEUE_TIMEOUT_SECS. @@ -132,6 +134,7 @@ class ClientDescriptor: narrow=self.narrow, client_type_name=self.client_type_name, bulk_message_deletion=self.bulk_message_deletion, + stream_typing_notifications=self.stream_typing_notifications, ) def __repr__(self) -> str: @@ -162,6 +165,7 @@ class ClientDescriptor: d["queue_timeout"], d.get("narrow", []), d.get("bulk_message_deletion", False), + d.get("stream_typing_notifications", False), ) ret.last_connection_time = d["last_connection_time"] return ret diff --git a/zerver/tornado/views.py b/zerver/tornado/views.py index 8b7c6dbd04..6dce89bc21 100644 --- a/zerver/tornado/views.py +++ b/zerver/tornado/views.py @@ -97,6 +97,9 @@ def get_events_backend( bulk_message_deletion: bool = REQ( default=False, json_validator=check_bool, intentionally_undocumented=True ), + stream_typing_notifications: bool = REQ( + default=False, json_validator=check_bool, intentionally_undocumented=True + ), ) -> HttpResponse: if all_public_streams and not user_profile.can_access_public_streams(): return json_error(_("User not authorized for this query")) @@ -136,6 +139,7 @@ def get_events_backend( last_connection_time=time.time(), narrow=narrow, bulk_message_deletion=bulk_message_deletion, + stream_typing_notifications=stream_typing_notifications, ) result = fetch_events(events_query) diff --git a/zerver/views/events_register.py b/zerver/views/events_register.py index 75889f98f5..fcb9715a61 100644 --- a/zerver/views/events_register.py +++ b/zerver/views/events_register.py @@ -52,6 +52,7 @@ def events_register_backend( # Any new fields of `client_capabilities` should be optional. Add them here. ("bulk_message_deletion", check_bool), ("user_avatar_url_field_optional", check_bool), + ("stream_typing_notifications", check_bool), ], value_validator=check_bool, ),