-
-
Notifications
You must be signed in to change notification settings - Fork 273
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
Conversation
fca75c4
to
067ff37
Compare
56ef2d0
to
590391d
Compare
@zulipbot add "PR needs review" |
590391d
to
d1b740e
Compare
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.
@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.
zulipterminal/helper.py
Outdated
@@ -101,6 +107,14 @@ class UnreadCounts(TypedDict): | |||
} | |||
|
|||
|
|||
STATE_ICON = { |
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.
Should we call it STATE_ICONS
instead?
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.
Hmm. Seems more apt 👍
I was also thinking if extracting this in symbols
would be more suitable?
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.
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.
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.
Just to resolve this discussion, I've migrated the STATE_ICON
to ui_mappings.py
as added to main recently via #1013.
8db0ba9
to
d47ee08
Compare
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.
@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 👍
zulipterminal/ui_tools/boxes.py
Outdated
email = self.message.get('sender_email', '') | ||
user = self.model.user_dict.get(email, None) |
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.
We will want to refactor this in future as we make changes to the user/presence details to improve encapsulation and move towards using id
s for lookup.
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.
Sure. I'll add a relavant TODO note 👍
tests/ui/test_ui_tools.py
Outdated
([STATUS_INACTIVE, 'alice', ' ', 'DAYDATETIME'], | ||
{'sender_full_name': 'bob'}), | ||
([' ', ' ', ' ', 'DAYDATETIME'], {'timestamp': 1532103779}), | ||
([STATUS_INACTIVE, 'alice', ' ', 'DAYDATETIME'], | ||
{'timestamp': 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.
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?
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.
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.
zulipterminal/ui_tools/views.py
Outdated
if is_sender_header: | ||
self.model._update_rendered_view(msg_box.message['id']) |
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.
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.
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.
Separated message box digging in 3rd commit.
Proposed a better approach for rendering in the last commit
d47ee08
to
b844b8c
Compare
b844b8c
to
62fc329
Compare
62fc329
to
776d795
Compare
8a7dfc3
to
7a7883e
Compare
7a7883e
to
b1be9b6
Compare
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.
@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.
zulipterminal/ui_tools/boxes.py
Outdated
update_required = False | ||
|
||
if self.need_recipient_header(): | ||
update_required = self[1][1].text != " " |
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.
Could we store self[1][1]
in a variable before so that it is more clear what is being checked?
tests/ui/test_ui_tools.py
Outdated
update_required, | ||
mocker, | ||
to_vary_in_each_message, | ||
header_needed, |
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.
header_needed
and mocker
are never used in the method body?
zulipterminal/ui_tools/views.py
Outdated
@@ -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)): |
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.
Since you're using self.body.log
more than once, you could extract it in a variable.
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.
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) ?
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 see that you're only mutating the attribute inside the loop, so extracting self.body.log
would work.
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.
(Assuming by not helpful you meant it is not going to update the original log.)
b1be9b6
to
5d2b7e4
Compare
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.
@Ezio-Sarthak Thanks for incorporating the changes. This seems to work well. 👍
@neiljp This looks good from my end.
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.
@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?
zulipterminal/ui_tools/views.py
Outdated
def update_msg_list_presence_markers(self) -> None: | ||
for msg_btn in self.body.log: |
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.
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'?
zulipterminal/ui_tools/views.py
Outdated
# Update a message box content header if required. | ||
msg_btn.original_widget.update_msg_content_header() |
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.
Would message_box = widget.original_widget
and message_box.update_content_header()
remove the need for a comment?
zulipterminal/ui_tools/boxes.py
Outdated
# FIXME: Render specific element (here content header) instead? | ||
super().__init__(self.main_view()) | ||
|
||
return update_required |
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.
Do we need this? Ah, you're using this in the test?
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.
Yes 😅
zulipterminal/ui_tools/boxes.py
Outdated
Update the content header of a message box (if required). | ||
""" | ||
update_required = False | ||
content_header = None |
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 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?
zulipterminal/ui_tools/boxes.py
Outdated
# Update the content header only if it's present and non-empty. | ||
if content_header is not None: | ||
update_required = content_header.text != " " |
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.
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.
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.
Makes sense. I'll go with author_is_present
and skip the comment 👍
zulipterminal/ui_tools/boxes.py
Outdated
|
||
if update_required: | ||
# Re initialize the message if update is required. | ||
# FIXME: Render specific element (here content header) instead? |
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 doesn't seem too much of an issue performance-wise right now, but let's open an issue for improving this.
tests/ui/test_ui_tools.py
Outdated
@@ -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", |
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 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.
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.
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 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).
@preetmishra No "resolve conversation"? If so, the GitHub UI is even less effective than I thought in this regard :/ |
5d2b7e4
to
0f696ba
Compare
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.
0f696ba
to
9bc51fb
Compare
@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)
|
What does this PR do?!
Commit flow
ui_mappings.py
(refactor)MessageBox
to update author field if present.Screenshots/GIFs
Fixes #896.