Skip to content

Commit

Permalink
refactor: boxes/model/ui: Show recipient names along with emails in PMs.
Browse files Browse the repository at this point in the history
Currently, PM narrows only display the delivery emails of the users. This
commit modifies the to_write_box to also display the names of the users
along with their emails. This commit also tidies up the private_box_view()
method by typing emails as List[str], and updating the corresponding
calls.

The get_invalid_recipient_emails() method in model.py has been modified and
renamed to get_invalid_recipients() to validate the combination of the
recipient's name and email.

Tests updated.
  • Loading branch information
prah23 committed Jan 26, 2021
1 parent 8ce2edb commit ef18640
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 40 deletions.
2 changes: 1 addition & 1 deletion tests/ui/test_ui_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1318,7 +1318,7 @@ def test_private_message_to_self(self, mocker):
mocker.patch.object(MessageBox, 'main_view')
msg_box = MessageBox(message, self.model, None)

assert msg_box.recipients_emails == '[email protected]'
assert msg_box.recipient_emails == ['[email protected]']
msg_box._is_private_message_to_self.assert_called_once_with()

@pytest.mark.parametrize('content, markup', [
Expand Down
7 changes: 4 additions & 3 deletions tests/ui_tools/test_boxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ def mock_external_classes(self, mocker, initial_index):

@pytest.fixture()
def write_box(self, mocker, users_fixture, user_groups_fixture,
streams_fixture, unicode_emojis):
streams_fixture, unicode_emojis, user_dict):
self.view.model.active_emoji_data = unicode_emojis
write_box = WriteBox(self.view)
write_box.view.users = users_fixture
write_box.model.user_dict = user_dict
write_box.model.user_group_names = [
groups['name'] for groups in user_groups_fixture]

Expand Down Expand Up @@ -589,7 +590,7 @@ def focus_val(x: str) -> int:
if write_box.focus_position == write_box.FOCUS_CONTAINER_HEADER:
write_box.header_write_box.focus_col = (focus_val(
initial_focus_col_name))
write_box.model.get_invalid_recipient_emails.return_value = []
write_box.model.get_invalid_recipients.return_value = []
write_box.model.user_dict = mocker.MagicMock()

write_box.keypress(size, tab_key)
Expand Down Expand Up @@ -621,7 +622,7 @@ def test_write_box_header_contents(self, write_box, expected_box_size,
elif msg_type == 'stream_edit':
write_box.stream_box_edit_view(1000)
else:
write_box.private_box_view(email='foo@gmail.com',
write_box.private_box_view(emails=['feedback@zulip.com'],
recipient_user_ids=[1])

assert len(write_box.header_write_box.widget_list) == expected_box_size
Expand Down
9 changes: 5 additions & 4 deletions zulipterminal/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -860,11 +860,12 @@ def _handle_typing_event(self, event: Event) -> None:
else:
raise RuntimeError("Unknown typing event operation")

def get_invalid_recipient_emails(self, recipient_emails: List[str]
) -> List[str]:
def get_invalid_recipients(self, recipients: List[str]) -> List[str]:
recipients_list = ['{} <{}>'.format(self.user_dict[email]['full_name'],
email) for email in self.user_dict]

return [email for email in recipient_emails
if email not in self.user_dict]
return [recipient for recipient in recipients
if recipient not in recipients_list]

def is_valid_stream(self, stream_name: str) -> bool:
for stream in self.stream_dict.values():
Expand Down
6 changes: 3 additions & 3 deletions zulipterminal/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,13 @@ def keypress(self, size: Tuple[int, int], key: str) -> Optional[str]:
stream_id=saved_draft['stream_id'],
)
elif saved_draft['type'] == 'private':
email_txt = saved_draft['display_recipient']
email_list = saved_draft['display_recipient']
recipient_user_ids = [
self.model.user_dict[email.strip()]['user_id']
for email in email_txt.split(",")
for email in email_list
]
self.write_box.private_box_view(
email=email_txt,
emails=email_list,
recipient_user_ids=recipient_user_ids,
)
content = saved_draft['content']
Expand Down
72 changes: 44 additions & 28 deletions zulipterminal/ui_tools/boxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,28 @@ def send_stop_typing_status(self) -> None:
self.send_next_typing_update = datetime.now()
self.idle_status_tracking = False

def private_box_view(self, *, email: str='',
def private_box_view(self, *, emails: Optional[List[str]]=None,
recipient_user_ids: Optional[List[int]]=None) -> None:
# Neither or both arguments should be set
assert ((email != '' and recipient_user_ids is not None)
or (email == '' and recipient_user_ids is None))
assert ((emails is not None and recipient_user_ids is not None)
or (emails is None and recipient_user_ids is None))

self.set_editor_mode()
if recipient_user_ids:
recipient_info = ''
if recipient_user_ids and emails:
self.recipient_user_ids = recipient_user_ids
self.recipient_emails = emails
for email in self.recipient_emails:
recipient_name = self.model.user_dict[email]['full_name']
recipient_info += (', ' if recipient_info else '')
recipient_info += "{} <{}>".format(recipient_name, email)
else:
self.recipient_user_ids = []
self.recipient_emails = []

self.send_next_typing_update = datetime.now()
self.to_write_box = ReadlineEdit("To: ", edit_text=email)
self.to_write_box = ReadlineEdit("To: ",
edit_text=recipient_info)
self.msg_write_box = ReadlineEdit(multiline=True)
self.msg_write_box.enable_autocomplete(
func=self.generic_autocomplete,
Expand Down Expand Up @@ -175,6 +183,12 @@ def track_idleness_and_update_status() -> None:

urwid.connect_signal(self.msg_write_box, 'change', on_type_send_status)

def update_recipient_emails(self, write_box: ReadlineEdit) -> None:
self.recipient_emails = re.findall(
r'[\w\.-]+@[\w\.-]+',
write_box.edit_text
)

def stream_box_view(self, stream_id: int, caption: str='', title: str='',
) -> None:
self.set_editor_mode()
Expand Down Expand Up @@ -466,10 +480,9 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
msg_id=self.msg_edit_id,
)
else:
recipient_emails = [email.strip() for email in
self.to_write_box.edit_text.split(',')]
self.update_recipient_emails(self.to_write_box)
success = self.model.send_private_message(
recipients=recipient_emails,
recipients=self.recipient_emails,
content=self.msg_write_box.edit_text
)
if success:
Expand All @@ -487,8 +500,9 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
elif is_command_key('SAVE_AS_DRAFT', key):
if not self.msg_edit_id:
if self.to_write_box:
self.update_recipient_emails(self.to_write_box)
message = Message(
display_recipient=self.to_write_box.edit_text,
display_recipient=self.recipient_emails,
content=self.msg_write_box.edit_text,
type='private',
)
Expand Down Expand Up @@ -551,19 +565,22 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
else:
header.focus_col = self.FOCUS_HEADER_BOX_STREAM
else:
recipient_box = header[self.FOCUS_HEADER_BOX_RECIPIENT]
recipient_emails = [email.strip() for email in
recipient_box.edit_text.split(',')]
invalid_emails = self.model.get_invalid_recipient_emails(
recipient_emails)
if invalid_emails:
invalid_emails_error = ('Invalid recipient(s) - '
+ ', '.join(invalid_emails))
self.view.set_footer_text(invalid_emails_error, 3)
self.update_recipient_emails(self.to_write_box)
recipients = [recipient_info.strip() for recipient_info
in self.to_write_box.edit_text.split(',')]
invalid_recipients = self.model.get_invalid_recipients(
recipients,
)
if invalid_recipients:
invalid_recipients_error = ('Invalid recipient(s) - '
+ ', '.join(
invalid_recipients))
self.view.set_footer_text(invalid_recipients_error, 3)
return key
users = self.model.user_dict
self.recipient_user_ids = [users[email]['user_id']
for email in recipient_emails]
for email in
self.recipient_emails]

if not self.msg_body_edit_enabled:
return key
Expand Down Expand Up @@ -614,19 +631,18 @@ def __init__(self, message: Message, model: Any,
if self._is_private_message_to_self():
recipient = self.message['display_recipient'][0]
self.recipients_names = recipient['full_name']
self.recipients_emails = self.model.user_email
self.recipient_emails = [self.model.user_email]
self.recipient_ids = self.model.user_id
else:
self.recipients_names = ', '.join(list(
recipient['full_name']
for recipient in self.message['display_recipient']
if recipient['email'] != self.model.user_email
))
self.recipients_emails = ', '.join(list(
recipient['email']
for recipient in self.message['display_recipient']
if recipient['email'] != self.model.user_email
))
self.recipient_emails = [recipient['email'] for recipient in
self.message['display_recipient']
if recipient['email']
!= self.model.user_email]
self.recipient_ids = [recipient['id'] for recipient
in self.message['display_recipient']
if recipient['id'] != self.model.user_id]
Expand Down Expand Up @@ -1251,7 +1267,7 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
if is_command_key('ENTER', key):
if self.message['type'] == 'private':
self.model.controller.view.write_box.private_box_view(
email=self.recipients_emails,
emails=self.recipient_emails,
recipient_user_ids=self.recipient_ids,
)
elif self.message['type'] == 'stream':
Expand All @@ -1263,7 +1279,7 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
elif is_command_key('STREAM_MESSAGE', key):
if self.message['type'] == 'private':
self.model.controller.view.write_box.private_box_view(
email=self.recipients_emails,
emails=self.recipient_emails,
recipient_user_ids=self.recipient_ids,
)
elif self.message['type'] == 'stream':
Expand Down Expand Up @@ -1301,7 +1317,7 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
elif is_command_key('REPLY_AUTHOR', key):
# All subscribers from recipient_ids are not needed here.
self.model.controller.view.write_box.private_box_view(
email=self.message['sender_email'],
emails=[self.message['sender_email']],
recipient_user_ids=[self.message['sender_id']],
)
elif is_command_key('MENTION_REPLY', key):
Expand Down
2 changes: 1 addition & 1 deletion zulipterminal/ui_tools/buttons.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def _narrow_with_compose(self, button: Any) -> None:
self.controller.narrow_to_user(self)
self._view.body.focus.original_widget.set_focus('footer')
self._view.write_box.private_box_view(
email=self.email,
emails=[self.email],
recipient_user_ids=[self.user_id]
)

Expand Down

0 comments on commit ef18640

Please sign in to comment.