New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Read receipts #18935
Read receipts #18935
Conversation
zerver/models.py
Outdated
# Use this for Django ORM queries to access read messages. | ||
# This custom SQL plays nice with our partial indexes. Grep | ||
# the code for example usage. | ||
return "flags & 1 <> 0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How did you confirm that this works with the partial indexes? It seems very possible to me that it does not and we need to create an index for this purpose.
Oh, I see this comment is copied. I would expect this to not have a good index.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said, I don't think we need an index for this operation -- we're fetching with a given message_id
, which does have a nice index, and it's fine to scan all the matches. So I think we should just replace the comment with one warning that this operation likely does not have an index, so should only be used for queries where another good index is already used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I'm not very familiar with partial indices. I thought this would be the same as where_unread
, and got the comment from it. Will change the comment and spend a bit of time reading about partial indices. Thanks! 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the comment to
# It is likely that this operation doesn't have an index. So,
# use this only for queries where another good index is present.
zerver/views/read_indicators.py
Outdated
.values_list("user_profile_id", flat=True) | ||
) | ||
|
||
return json_success({"user_ids": list(user_ids)}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks about right to me! I think we might need additional filtering to exclude deactivated users; I think that a UX question I don't understand clearly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused about excluding deactivated users. Since their read activity was before their deactivation, we may have to show their read receipts too. Like we presumably show deactivated users' mentions in messages before their account deactivation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did this in a different commit to make it easier to remove in case we decide we don't want to filter.
zproject/urls.py
Outdated
@@ -354,6 +355,8 @@ | |||
# typing -> zerver.views.typing | |||
# POST sends a typing notification event to recipients | |||
rest_path("typing", POST=send_notification_backend), | |||
# read_by -> zerver.views.read_indicators | |||
rest_path("read_by/<int:message_id>", GET=read_by_users), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be something like GET /message/{message_id}/read_receipts
, to follow REST
conventions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, changed. Thanks, didn't know.
static/js/click_handlers.js
Outdated
@@ -205,6 +206,11 @@ export function initialize() { | |||
message_flags.toggle_starred_and_update_server(message); | |||
}); | |||
|
|||
$("#main_div").on("click", ".show_readby_users", (e) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think show_read_indicators
is probably a better name.
I'd also consider clarifying the interface between this and read_indicators.js
, to try to do the rows.js
logic here only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to show_read_receipts
and moved the rows.js
logic to this.
This seems plausible as a direction; posted a few quick comments on details and naming. I think it'd be best to pick a single variable name for the feature, e.g. |
Thanks for the review, @timabbott! Will continue with the rest of the work after making those changes. |
092727e
to
722de40
Compare
a4d3ec9
to
72d38f6
Compare
As an update, I made the suggested changes, added backend tests, made slight changes to js code like hiding the author of the message in the tooltip. I'm going to write API docs and examples and then add a few js tests. |
ee74091
to
0becb91
Compare
I think the API endpoint part of this is done. I might have to merge the first two commits. Kept them separate for now to keep it easier to review. |
0becb91
to
9653b53
Compare
9653b53
to
e89aed9
Compare
e89aed9
to
5a5d58b
Compare
5a5d58b
to
cb85c3a
Compare
41f81a9
to
1172c52
Compare
f9cf39c
to
fbee328
Compare
<a class="view_read_receipts" data-message-id="{{message_id}}" tabindex="0"> | ||
<i class="zulip-icon zulip-icon-readreceipts" aria-label="{{#tr}}View read receipts{{/tr}}"></i> {{t "View read receipts" }} | ||
</a> | ||
</li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be hidden for spectators, who have no access to the relevant API endpoint. I think this can be done by just adding class="hidden-for-spectators"
to the li
element.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this class.
12f1a09
to
53b09ea
Compare
53b09ea
to
0b0866c
Compare
I concur with that assessment. (There's also another API changelog renumbering, but those are quick). |
fb0274b
to
c0b2a5d
Compare
9ea7425
to
131947a
Compare
Updated with a handful of important changes:
With those changes, I think this is good to merge to |
131947a
to
d559292
Compare
The previous version with e.target would give the element that was clicked lying inside an element with '.view_user_profile'. One would usually expect "data-user-id" to be attached to the same element with ".view_user_profile" instead of any of its children. So, to just look for "data-user-id" in the element with that class, instead of any of its chidren, this commit changes e.target to e.currentTarget.
Previously, our modal system prevented opening a modal when one was already open. It appears this was implemented to work around the fact that we're using Micromodal selectors to determine if a modal is open (and those don't update until after an animation frame). We'd like to support opening the full user profile and manage user modals while read receipts is open. While we could work around this in that place, it feels like one needs a lot of documentation in order to add a setTimeout in those code paths. So we instead make open_modal support this, with a guard to prevent infinite recursion in case of future bugs. Note that dialog_widget was already closing modals before opening the next one, so this is a behavior change only for our 3 modals that do not use dialog_widget. (I'm not sure why the `dialog_widget` modals did not already require a delay, but likely there's some CSS difference). We likely will want to redo this to instead use a better state tracking system. See https://chat.zulip.org/#narrow/stream/49-development-help/topic/close.20and.20open.20another.20modal.20immediately for discussion.
d559292
to
27e9ef5
Compare
Now that we've split this out from the enormous actions.py, it makes sense to include this in the set of inputs for generating the database.
27e9ef5
to
432019c
Compare
Following the integration of #22657, this needed a few tweaks:
With those changes, I've marked this to merge once CI passes. I think there are two major forms of finishing work that we'll want to do:
If necessary we can slow roll the feature in a few different ways; the simplest is just to delay the migration that enables the realm setting for existing closed organizations, such that only those few organizations that discover it and enable it would have it at first (but the privacy setting would be available to everyone). |
Adds an API endpoint for accessing read receipts for other users, as well as a modal UI for displaying that information. Enables the previously merged privacy settings UI for managing whether a user makes read receipts data available to other users. Documentation is pending, and we'll likely want to link to the documentation with help_settings_link once it is complete. Fixes zulip#3618. Co-authored-by: Tim Abbott <tabbott@zulip.com>
432019c
to
13041e0
Compare
#3618