mirror of https://github.com/zulip/zulip.git
subscriptions: Send update events for `is_muted` property.
In Zulip 2.1.0, the `is_muted` stream subscription property was added and replaced the `in_home_view` property. But the server has still only been sending subscription update events with the `in_home_view` property. Updates `do_change_subscription_property` to send a subscription update event for both `is_muted` and `in_home_view`, so that clients can fully migrate away from using `in_home_view` allowing us to eventually remove it completely.
This commit is contained in:
parent
47e5ccf086
commit
885c3d6593
|
@ -20,6 +20,15 @@ format used by the Zulip server that they are interacting with.
|
||||||
|
|
||||||
## Changes in Zulip 6.0
|
## Changes in Zulip 6.0
|
||||||
|
|
||||||
|
**Feature level 139**
|
||||||
|
|
||||||
|
* [`GET /get-events`](/api/get-events): When a user mutes or unmutes
|
||||||
|
their subscription to a stream, a `subscription` update event
|
||||||
|
is now sent for the `is_muted` property and for the deprecated
|
||||||
|
`in_home_view` property to support clients fully migrating to use the
|
||||||
|
`is_muted` property. Prior to this feature level, only one event was
|
||||||
|
sent to clients with the deprecated `in_home_view` property.
|
||||||
|
|
||||||
**Feature level 138**
|
**Feature level 138**
|
||||||
|
|
||||||
* [`POST /register`](/api/register-queue), [`GET
|
* [`POST /register`](/api/register-queue), [`GET
|
||||||
|
@ -228,7 +237,7 @@ No changes; feature level used for Zulip 5.0 release.
|
||||||
|
|
||||||
**Feature level 111**
|
**Feature level 111**
|
||||||
|
|
||||||
* [`POST /subscriptions/properties`](/api/update-subscription-settings):
|
* [`POST /users/me/subscriptions/properties`](/api/update-subscription-settings):
|
||||||
Removed `subscription_data` from response object, replacing it with
|
Removed `subscription_data` from response object, replacing it with
|
||||||
`ignored_parameters_unsupported`.
|
`ignored_parameters_unsupported`.
|
||||||
|
|
||||||
|
@ -1137,7 +1146,8 @@ No changes; feature level used for Zulip 3.0 release.
|
||||||
`demote_inactive_streams` display settings.
|
`demote_inactive_streams` display settings.
|
||||||
* `enable_stream_sounds` was renamed to
|
* `enable_stream_sounds` was renamed to
|
||||||
`enable_stream_audible_notifications`.
|
`enable_stream_audible_notifications`.
|
||||||
* Deprecated `in_home_view`, replacing it with the more readable
|
* [`POST /users/me/subscriptions/properties`](/api/update-subscription-settings):
|
||||||
|
Deprecated `in_home_view`, replacing it with the more readable
|
||||||
`is_muted` (with the opposite meaning).
|
`is_muted` (with the opposite meaning).
|
||||||
* Custom profile fields: Added `EXTERNAL_ACCOUNT` field type.
|
* Custom profile fields: Added `EXTERNAL_ACCOUNT` field type.
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.4.3"
|
||||||
# Changes should be accompanied by documentation explaining what the
|
# Changes should be accompanied by documentation explaining what the
|
||||||
# new level means in templates/zerver/api/changelog.md, as well as
|
# new level means in templates/zerver/api/changelog.md, as well as
|
||||||
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
||||||
API_FEATURE_LEVEL = 138
|
API_FEATURE_LEVEL = 139
|
||||||
|
|
||||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
||||||
# only when going from an old version of the code to a newer version. Bump
|
# only when going from an old version of the code to a newer version. Bump
|
||||||
|
|
|
@ -769,19 +769,14 @@ def do_change_subscription_property(
|
||||||
acting_user: Optional[UserProfile],
|
acting_user: Optional[UserProfile],
|
||||||
) -> None:
|
) -> None:
|
||||||
database_property_name = property_name
|
database_property_name = property_name
|
||||||
event_property_name = property_name
|
|
||||||
database_value = value
|
database_value = value
|
||||||
event_value = value
|
|
||||||
|
|
||||||
# For this property, is_muted is used in the database, but
|
# For this property, is_muted is used in the database, but
|
||||||
# in_home_view in the API, since we haven't migrated the events
|
# in_home_view is still in the API, since we haven't fully
|
||||||
# API to the new name yet.
|
# migrated to the new name yet.
|
||||||
if property_name == "in_home_view":
|
if property_name == "in_home_view":
|
||||||
database_property_name = "is_muted"
|
database_property_name = "is_muted"
|
||||||
database_value = not value
|
database_value = not value
|
||||||
if property_name == "is_muted":
|
|
||||||
event_property_name = "in_home_view"
|
|
||||||
event_value = not value
|
|
||||||
|
|
||||||
old_value = getattr(sub, database_property_name)
|
old_value = getattr(sub, database_property_name)
|
||||||
setattr(sub, database_property_name, database_value)
|
setattr(sub, database_property_name, database_value)
|
||||||
|
@ -803,11 +798,26 @@ def do_change_subscription_property(
|
||||||
).decode(),
|
).decode(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# This first in_home_view event is deprecated and will be removed
|
||||||
|
# once clients are migrated to handle the subscription update event
|
||||||
|
# with is_muted as the property name.
|
||||||
|
if database_property_name == "is_muted":
|
||||||
|
event_value = not database_value
|
||||||
|
in_home_view_event = dict(
|
||||||
|
type="subscription",
|
||||||
|
op="update",
|
||||||
|
property="in_home_view",
|
||||||
|
value=event_value,
|
||||||
|
stream_id=stream.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
send_event(user_profile.realm, in_home_view_event, [user_profile.id])
|
||||||
|
|
||||||
event = dict(
|
event = dict(
|
||||||
type="subscription",
|
type="subscription",
|
||||||
op="update",
|
op="update",
|
||||||
property=event_property_name,
|
property=database_property_name,
|
||||||
value=event_value,
|
value=database_value,
|
||||||
stream_id=stream.id,
|
stream_id=stream.id,
|
||||||
)
|
)
|
||||||
send_event(user_profile.realm, event, [user_profile.id])
|
send_event(user_profile.realm, event, [user_profile.id])
|
||||||
|
|
|
@ -697,8 +697,9 @@ paths:
|
||||||
description: |
|
description: |
|
||||||
Event sent to a user's clients when a property of the user's
|
Event sent to a user's clients when a property of the user's
|
||||||
subscription to a stream has been updated. This event is used
|
subscription to a stream has been updated. This event is used
|
||||||
only for personal properties like `is_muted`; see the `stream` event
|
only for personal properties like `is_muted` or `pin_to_top`.
|
||||||
for global properties of a stream.
|
See the [stream update event](/api/get-events#stream-update)
|
||||||
|
for updates to global properties of a stream.
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
$ref: "#/components/schemas/EventIdSchema"
|
$ref: "#/components/schemas/EventIdSchema"
|
||||||
|
@ -718,13 +719,19 @@ paths:
|
||||||
property:
|
property:
|
||||||
type: string
|
type: string
|
||||||
description: |
|
description: |
|
||||||
The property of the subscription which has changed. See
|
The property of the subscription which has changed. For details on the
|
||||||
[/users/me/subscriptions/properties GET](/api/update-subscription-settings)
|
various subscription properties that a user can change, see
|
||||||
for details on the various properties of a stream.
|
[POST /users/me/subscriptions/properties](/api/update-subscription-settings).
|
||||||
|
|
||||||
Clients should generally handle an unknown property received here without
|
Clients should generally handle an unknown property received here without
|
||||||
crashing, since that will naturally happen when connecting to a Zulip
|
crashing, since that will naturally happen when connecting to a Zulip
|
||||||
server running a new version that adds a new subscription property.
|
server running a new version that adds a new subscription property.
|
||||||
|
|
||||||
|
**Changes**: As of Zulip 6.0 (feature level 139), updates to the `is_muted`
|
||||||
|
property or the deprecated `in_home_view` property will send two `subscription`
|
||||||
|
update events, one for each property, to support clients fully migrating to
|
||||||
|
use the `is_muted` property. Prior to this feature level, updates to either
|
||||||
|
property only sent one event with the deprecated `in_home_view` property.
|
||||||
value:
|
value:
|
||||||
description: |
|
description: |
|
||||||
The new value of the changed property.
|
The new value of the changed property.
|
||||||
|
@ -8773,8 +8780,14 @@ paths:
|
||||||
- `"color"`: The hex value of the user's display color for the stream.
|
- `"color"`: The hex value of the user's display color for the stream.
|
||||||
|
|
||||||
- `"is_muted"`: Whether the stream is [muted](/help/mute-a-stream).<br>
|
- `"is_muted"`: Whether the stream is [muted](/help/mute-a-stream).<br>
|
||||||
|
**Changes**: As of Zulip 6.0 (feature level 139), updating either
|
||||||
|
`"is_muted"` or `"in_home_view"` generates two [subscription update
|
||||||
|
events](/api/get-events#subscription-update), one for each property,
|
||||||
|
that are sent to clients. Prior to this feature level, updating either
|
||||||
|
property only generated a subscription update event for
|
||||||
|
`"in_home_view"`. <br>
|
||||||
**Changes**: Prior to Zulip 2.1.0, this feature was represented
|
**Changes**: Prior to Zulip 2.1.0, this feature was represented
|
||||||
by the more confusingly named `in_home_view` (with the
|
by the more confusingly named `"in_home_view"` (with the
|
||||||
opposite value: `in_home_view=!is_muted`); for
|
opposite value: `in_home_view=!is_muted`); for
|
||||||
backwards-compatibility, modern Zulip still accepts that property.
|
backwards-compatibility, modern Zulip still accepts that property.
|
||||||
|
|
||||||
|
|
|
@ -1481,6 +1481,55 @@ class NormalActionsTest(BaseAction):
|
||||||
value=pinned,
|
value=pinned,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_mute_and_unmute_stream(self) -> None:
|
||||||
|
stream = get_stream("Denmark", self.user_profile.realm)
|
||||||
|
sub = get_subscription(stream.name, self.user_profile)
|
||||||
|
|
||||||
|
# While migrating events API from in_home_view to is_muted:
|
||||||
|
# First, test in_home_view sends 2 events: in_home_view and is_muted.
|
||||||
|
do_change_subscription_property(
|
||||||
|
self.user_profile, sub, stream, "in_home_view", False, acting_user=None
|
||||||
|
)
|
||||||
|
|
||||||
|
events = self.verify_action(
|
||||||
|
lambda: do_change_subscription_property(
|
||||||
|
self.user_profile, sub, stream, "in_home_view", True, acting_user=None
|
||||||
|
),
|
||||||
|
num_events=2,
|
||||||
|
)
|
||||||
|
check_subscription_update(
|
||||||
|
"events[0]",
|
||||||
|
events[0],
|
||||||
|
property="in_home_view",
|
||||||
|
value=True,
|
||||||
|
)
|
||||||
|
check_subscription_update(
|
||||||
|
"events[1]",
|
||||||
|
events[1],
|
||||||
|
property="is_muted",
|
||||||
|
value=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Then, test is_muted also sends both events, in the same order.
|
||||||
|
events = self.verify_action(
|
||||||
|
lambda: do_change_subscription_property(
|
||||||
|
self.user_profile, sub, stream, "is_muted", True, acting_user=None
|
||||||
|
),
|
||||||
|
num_events=2,
|
||||||
|
)
|
||||||
|
check_subscription_update(
|
||||||
|
"events[0]",
|
||||||
|
events[0],
|
||||||
|
property="in_home_view",
|
||||||
|
value=False,
|
||||||
|
)
|
||||||
|
check_subscription_update(
|
||||||
|
"events[1]",
|
||||||
|
events[1],
|
||||||
|
property="is_muted",
|
||||||
|
value=True,
|
||||||
|
)
|
||||||
|
|
||||||
def test_change_stream_notification_settings(self) -> None:
|
def test_change_stream_notification_settings(self) -> None:
|
||||||
for setting_name in ["email_notifications"]:
|
for setting_name in ["email_notifications"]:
|
||||||
stream = get_stream("Denmark", self.user_profile.realm)
|
stream = get_stream("Denmark", self.user_profile.realm)
|
||||||
|
|
|
@ -3016,7 +3016,7 @@ class SubscriptionPropertiesTest(ZulipTestCase):
|
||||||
|
|
||||||
events: List[Mapping[str, Any]] = []
|
events: List[Mapping[str, Any]] = []
|
||||||
property_name = "is_muted"
|
property_name = "is_muted"
|
||||||
with self.tornado_redirected_to_list(events, expected_num_events=1):
|
with self.tornado_redirected_to_list(events, expected_num_events=2):
|
||||||
result = self.api_post(
|
result = self.api_post(
|
||||||
test_user,
|
test_user,
|
||||||
"/api/v1/users/me/subscriptions/properties",
|
"/api/v1/users/me/subscriptions/properties",
|
||||||
|
@ -3035,6 +3035,8 @@ class SubscriptionPropertiesTest(ZulipTestCase):
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
self.assertEqual(events[0]["event"]["property"], "in_home_view")
|
self.assertEqual(events[0]["event"]["property"], "in_home_view")
|
||||||
self.assertEqual(events[0]["event"]["value"], False)
|
self.assertEqual(events[0]["event"]["value"], False)
|
||||||
|
self.assertEqual(events[1]["event"]["property"], "is_muted")
|
||||||
|
self.assertEqual(events[1]["event"]["value"], True)
|
||||||
sub = Subscription.objects.get(
|
sub = Subscription.objects.get(
|
||||||
recipient__type=Recipient.STREAM,
|
recipient__type=Recipient.STREAM,
|
||||||
recipient__type_id=subs[0]["stream_id"],
|
recipient__type_id=subs[0]["stream_id"],
|
||||||
|
@ -3043,7 +3045,7 @@ class SubscriptionPropertiesTest(ZulipTestCase):
|
||||||
self.assertEqual(sub.is_muted, True)
|
self.assertEqual(sub.is_muted, True)
|
||||||
|
|
||||||
legacy_property_name = "in_home_view"
|
legacy_property_name = "in_home_view"
|
||||||
with self.tornado_redirected_to_list(events, expected_num_events=1):
|
with self.tornado_redirected_to_list(events, expected_num_events=2):
|
||||||
result = self.api_post(
|
result = self.api_post(
|
||||||
test_user,
|
test_user,
|
||||||
"/api/v1/users/me/subscriptions/properties",
|
"/api/v1/users/me/subscriptions/properties",
|
||||||
|
@ -3062,6 +3064,8 @@ class SubscriptionPropertiesTest(ZulipTestCase):
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
self.assertEqual(events[0]["event"]["property"], "in_home_view")
|
self.assertEqual(events[0]["event"]["property"], "in_home_view")
|
||||||
self.assertEqual(events[0]["event"]["value"], True)
|
self.assertEqual(events[0]["event"]["value"], True)
|
||||||
|
self.assertEqual(events[1]["event"]["property"], "is_muted")
|
||||||
|
self.assertEqual(events[1]["event"]["value"], False)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
sub = Subscription.objects.get(
|
sub = Subscription.objects.get(
|
||||||
recipient__type=Recipient.STREAM,
|
recipient__type=Recipient.STREAM,
|
||||||
|
@ -3070,7 +3074,7 @@ class SubscriptionPropertiesTest(ZulipTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(sub.is_muted, False)
|
self.assertEqual(sub.is_muted, False)
|
||||||
|
|
||||||
with self.tornado_redirected_to_list(events, expected_num_events=1):
|
with self.tornado_redirected_to_list(events, expected_num_events=2):
|
||||||
result = self.api_post(
|
result = self.api_post(
|
||||||
test_user,
|
test_user,
|
||||||
"/api/v1/users/me/subscriptions/properties",
|
"/api/v1/users/me/subscriptions/properties",
|
||||||
|
@ -3089,6 +3093,8 @@ class SubscriptionPropertiesTest(ZulipTestCase):
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
self.assertEqual(events[0]["event"]["property"], "in_home_view")
|
self.assertEqual(events[0]["event"]["property"], "in_home_view")
|
||||||
self.assertEqual(events[0]["event"]["value"], False)
|
self.assertEqual(events[0]["event"]["value"], False)
|
||||||
|
self.assertEqual(events[1]["event"]["property"], "is_muted")
|
||||||
|
self.assertEqual(events[1]["event"]["value"], True)
|
||||||
|
|
||||||
sub = Subscription.objects.get(
|
sub = Subscription.objects.get(
|
||||||
recipient__type=Recipient.STREAM,
|
recipient__type=Recipient.STREAM,
|
||||||
|
|
Loading…
Reference in New Issue