Skip to content
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

Show sender's presence status in message content header #987

Merged
merged 4 commits into from
Jul 4, 2021

Conversation

Ezio-Sarthak
Copy link
Member

@Ezio-Sarthak Ezio-Sarthak commented Apr 7, 2021

What does this PR do?!

  • Adds sender's presence status marker in a message content header

Commit flow

  • Centralize the state icons in ui_mappings.py (refactor)
  • Add state marker as a prefix to sender names in the message header.
  • Add helper in MessageBox to update author field if present.
  • Add a method to render presence markers in messages regularly.

Screenshots/GIFs

Screenshot from 2021-06-26 23-02-58

Fixes #896.

@zulipbot zulipbot added size: L [Automatic label added by zulipbot] area: UI General user interface update enhancement New feature or request labels Apr 7, 2021
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch from fca75c4 to 067ff37 Compare April 7, 2021 15:58
@zulipbot zulipbot added size: XL [Automatic label added by zulipbot] and removed size: L [Automatic label added by zulipbot] labels Apr 7, 2021
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch 3 times, most recently from 56ef2d0 to 590391d Compare April 10, 2021 08:35
@Ezio-Sarthak
Copy link
Member Author

@zulipbot add "PR needs review"

@zulipbot zulipbot added the PR needs review PR requires feedback to proceed label Apr 11, 2021
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch from 590391d to d1b740e Compare April 17, 2021 03:37
Copy link
Member

@preetmishra preetmishra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ezio-Sarthak Thanks for working on this! I have tested this locally and it seems to work well. 👍

I have left some quick comments for the first review iteration. Let's squash the last commit as you mention in the PR description.

@@ -101,6 +107,14 @@ class UnreadCounts(TypedDict):
}


STATE_ICON = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we call it STATE_ICONS instead?

Copy link
Member Author

@Ezio-Sarthak Ezio-Sarthak Apr 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Seems more apt 👍

I was also thinking if extracting this in symbols would be more suitable?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When naming like this, it's good to think of how it's used - STATE_ICONS['active'] suggests there are more than one active one? Generally I err towards the non-plural for this reason.

Also the values are icons, but the keys aren't - so as always, naming is tricky to get perfect!

This relates application state values to representation, a little like edit_mode_captions, so perhaps it belongs in with that, though I'm not keen on helper.py for that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to resolve this discussion, I've migrated the STATE_ICON to ui_mappings.py as added to main recently via #1013.

@preetmishra preetmishra added PR awaiting update PR has been reviewed & is awaiting update or response to reviewer feedback and removed PR needs review PR requires feedback to proceed labels Apr 18, 2021
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch 2 times, most recently from 8db0ba9 to d47ee08 Compare April 19, 2021 09:12
Copy link
Collaborator

@neiljp neiljp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ezio-Sarthak I do enjoy this feature, so wanted to give some more focused feedback.

Our (event+actions)->message-view handling is something I can ideally see being refactored soon, but what you have here does seem to work fine for the most part 👍

Comment on lines 1208 to 1336
email = self.message.get('sender_email', '')
user = self.model.user_dict.get(email, None)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will want to refactor this in future as we make changes to the user/presence details to improve encapsulation and move towards using ids for lookup.

Copy link
Member Author

@Ezio-Sarthak Ezio-Sarthak Apr 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I'll add a relavant TODO note 👍

Comment on lines 1790 to 1808
([STATUS_INACTIVE, 'alice', ' ', 'DAYDATETIME'],
{'sender_full_name': 'bob'}),
([' ', ' ', ' ', 'DAYDATETIME'], {'timestamp': 1532103779}),
([STATUS_INACTIVE, 'alice', ' ', 'DAYDATETIME'],
{'timestamp': 0}),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure whether this is the right test to add it to, but we're not extending the testing to cover the range of activity markers, or being a bot?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Currently, in the PR, I've marked all users (including bots) as per their activity. Thus, a bot would currently be marked inactive.

Yes, my intent was to just amend the tests re header content to be shown (currently), not testing the activity marker rendering in particular.

Comment on lines 549 to 550
if is_sender_header:
self.model._update_rendered_view(msg_box.message['id'])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new method you've added does a lot of digging into MessageBox - it seems like it would be simpler to have the logic inside that class/object?

I'm also not sure that model._update_rendered_view is required here, or that maybe we can try a different approach. Most of the explicit logic there is more for reordering - though other handlers do use it for updating, albeit one message at a time. Given the way that the latter method works, this is going to filter every message and re-generate/render them all, one by one. Each box does need updating, but maybe we can add a method to MessageBox to just update the one element?

I'm slightly concerned with the asynch here, as it's yet another function updating the message list in addition to events, conceptually in parallel.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separated message box digging in 3rd commit.
Proposed a better approach for rendering in the last commit

@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch from d47ee08 to b844b8c Compare April 27, 2021 03:49
@Ezio-Sarthak
Copy link
Member Author

@zulipbot remove "PR awaiting update"
@zulipbot add "PR needs review"

@zulipbot zulipbot added PR needs review PR requires feedback to proceed and removed PR awaiting update PR has been reviewed & is awaiting update or response to reviewer feedback labels Apr 27, 2021
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch from b844b8c to 62fc329 Compare April 28, 2021 10:54
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch from 62fc329 to 776d795 Compare May 29, 2021 08:36
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch 4 times, most recently from 8a7dfc3 to 7a7883e Compare June 22, 2021 03:53
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch from 7a7883e to b1be9b6 Compare June 25, 2021 17:17
Copy link
Member

@preetmishra preetmishra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ezio-Sarthak Thanks for the update! This continues to work well. 👍

I have left some minor in-line comments. Other than that, this looks pretty close.

We could log issues for partial updates and also the bot presence marker depending upon whether you would take them next once the PR is merged.

update_required = False

if self.need_recipient_header():
update_required = self[1][1].text != " "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we store self[1][1] in a variable before so that it is more clear what is being checked?

update_required,
mocker,
to_vary_in_each_message,
header_needed,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

header_needed and mocker are never used in the method body?

@@ -547,6 +547,18 @@ def get_next_unread_pm(self) -> Optional[int]:
return pm
return None

def update_msg_list_presence_markers(self) -> None:
for index in range(len(self.body.log)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're using self.body.log more than once, you could extract it in a variable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, though I think it would be not helpful for the line L558 (where we're updating self.body.log itself)?

Or do you mean updating the whole message list outside the loop in the end:
self.body.log = msg_list (if msg_list is the variable for instance) ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that you're only mutating the attribute inside the loop, so extracting self.body.log would work.

Copy link
Member

@preetmishra preetmishra Jun 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Assuming by not helpful you meant it is not going to update the original log.)

@preetmishra preetmishra added PR awaiting update PR has been reviewed & is awaiting update or response to reviewer feedback and removed PR needs review PR requires feedback to proceed labels Jun 26, 2021
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch from b1be9b6 to 5d2b7e4 Compare June 26, 2021 17:22
@Ezio-Sarthak Ezio-Sarthak added PR needs review PR requires feedback to proceed and removed PR awaiting update PR has been reviewed & is awaiting update or response to reviewer feedback labels Jun 26, 2021
Copy link
Member

@preetmishra preetmishra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ezio-Sarthak Thanks for incorporating the changes. This seems to work well. 👍

@neiljp This looks good from my end.

Copy link
Collaborator

@neiljp neiljp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ezio-Sarthak Thanks for the last update - just a few points inline left I hope :)

@preetmishra If you are satisfied with the points you raised in the review, can you resolve those?

Comment on lines 550 to 556
def update_msg_list_presence_markers(self) -> None:
for msg_btn in self.body.log:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's aim to use message since we have space. Is the loop variable more accurately a widget wrapper around a message_box, not a 'button'?

Comment on lines 552 to 553
# Update a message box content header if required.
msg_btn.original_widget.update_msg_content_header()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would message_box = widget.original_widget and message_box.update_content_header() remove the need for a comment?

# FIXME: Render specific element (here content header) instead?
super().__init__(self.main_view())

return update_required
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? Ah, you're using this in the test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes 😅

Update the content header of a message box (if required).
"""
update_required = False
content_header = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't the content_header, but the author field? If so, let's name it that? Maybe set author_column = 1 and use that in the indexing to make it clearer?

Comment on lines 1377 to 1379
# Update the content header only if it's present and non-empty.
if content_header is not None:
update_required = content_header.text != " "
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not obvious where the " " test comes from - it's the default author text, when there's no author in the header, right? That's partly unclear due to the content_header variable name, but "non empty" and "content header" just repeat the code, so if we're going to include a comment, let's make it more useful - or set a variable like author_is_present = ... to help.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I'll go with author_is_present and skip the comment 👍


if update_required:
# Re initialize the message if update is required.
# FIXME: Render specific element (here content header) instead?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem too much of an issue performance-wise right now, but let's open an issue for improving this.

@@ -2211,6 +2211,52 @@ def test_main_view_generates_EDITED_label(
assert label[0].text == "EDITED"
assert label[1][1] == 7

@pytest.mark.parametrize(
"message",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is specifically a stream message, though the behavior shouldn't vary across message types. Can we add a note here regarding that we should refactor this? We have other tests with a single parametrize entry, but it's a little misleading.

Copy link
Member Author

@Ezio-Sarthak Ezio-Sarthak Jul 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I used basically it as base message template, which I'm modifying as per the to_vary_in_each_message parameters. Surely I'll add a note here 👍.

@neiljp neiljp added PR awaiting update PR has been reviewed & is awaiting update or response to reviewer feedback and removed PR needs review PR requires feedback to proceed labels Jul 1, 2021
@preetmishra
Copy link
Member

@neiljp I don't have the "resolve" button available on my end.

This commit centralizes the use of state icons corresponding to
a user status in `ui_mappings.py` as `STATE_ICON`.
This commit adds a status marker right before the sender's name in a
message content header. The users' dict from model is used to get
status of the sender. The default status of sender is kept `inactive`.

NOTE: Currently bots are marked as `inactive`. A later version would
be to render markers for bots as well.

Tests amended (Message content header related).
@neiljp
Copy link
Collaborator

neiljp commented Jul 4, 2021

@preetmishra No "resolve conversation"? If so, the GitHub UI is even less effective than I thought in this regard :/

@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch from 5d2b7e4 to 0f696ba Compare July 4, 2021 09:08
@Ezio-Sarthak Ezio-Sarthak added PR needs review PR requires feedback to proceed and removed PR awaiting update PR has been reviewed & is awaiting update or response to reviewer feedback labels Jul 4, 2021
Ezio-Sarthak and others added 2 commits July 5, 2021 00:11
This commit adds a method to update author status of a specific message
box (if required).

The current logic re-builds the whole message box if an update is required.
This might need improvement as to update a specific element only. (Though
that might prove useful only if that element is rendered via a dedicated
method).

Tests added.
This commit:
 * introduces a method `update_message_list_status_markers` in middle
   column view class. It would be responsible for rendering the status
   markers (if required) in the message list.
 * adds presence renderer function to the handler `start_presence_updates`.
   This way, the method `update_message_list_status_markers` is called
   every minute.

The helper `update_message_list_status_markers` uses MessageBox method
`update_message_author_status` (added in previous commit) to update
message boxes if author field is present.

Fixes zulip#896.
@Ezio-Sarthak Ezio-Sarthak force-pushed the user-presence-stats-in-msg branch from 0f696ba to 9bc51fb Compare July 4, 2021 18:51
@neiljp
Copy link
Collaborator

neiljp commented Jul 4, 2021

@Ezio-Sarthak Thanks for making the updates - this will be great to use! I'm going to merge shortly 🎉

Thoughts for some follow-ups that we should discuss and implement promptly or file as issues: (some we discussed already)

  • Show bot markers (this was also suggested in my role-markers PR)
  • Handle "unavailable" visibility and explicit changes (are they events?)
  • Only update the status rather than the entire box - maybe not that tricky?
  • Show user presence in PM compose?
  • Show user presence in user mentions?

@neiljp neiljp merged commit cb5b7ae into zulip:main Jul 4, 2021
@neiljp neiljp added this to the Next Release milestone Jul 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: UI General user interface update enhancement New feature or request PR needs review PR requires feedback to proceed size: XL [Automatic label added by zulipbot]
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Show sender/recipient presence status in messages
4 participants