def narrow_to_topic(self, button: Any) -> None: already_narrowed = self.model.set_narrow(stream=button.caption, topic=button.title) if already_narrowed: return self.update = False # store the steam id in the model (required for get_message_ids...) self.model.stream_id = button.stream_id msg_id_list = self.model.get_message_ids_in_current_narrow() if len(msg_id_list) == 0: get_msg_opts = dict(num_before=30, num_after=10, anchor=None) # type: GetMessagesArgs if hasattr(button, 'message'): get_msg_opts['anchor'] = button.message['id'] self.model.get_messages(**get_msg_opts) msg_id_list = self.model.get_message_ids_in_current_narrow() if hasattr(button, 'message'): w_list = create_msg_box_list(self.model, msg_id_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_id_list) self._finalize_show(w_list)
def narrow_to_topic(self, button: Any) -> None: if self.model.narrow == [['stream', button.caption], ['topic', button.title]]: return if hasattr(button, 'message') and self.model.narrow == []: self.model.focus_all_msg = button.message['id'] self.model.narrow = [["stream", button.caption], ["topic", button.title]] self.model.num_after = 10 self.model.num_before = 30 if hasattr(button, 'message'): self.model.anchor = button.message['id'] classified_msgs = self.model.load_old_messages(False) else: classified_msgs = self.model.load_old_messages(True) messages = list(itertools.chain.from_iterable( classified_msgs.values())) if len(messages) < 41: self.model.update = True if hasattr(button, 'message'): w_list, focus_msg = create_msg_box_list(messages, self.model, narrow=True, id=button.message['id']) focus_msg += 1 if len(w_list) == 1: focus_msg = 0 else: w_list, focus_msg = create_msg_box_list(messages, self.model, narrow=True) self.model.msg_view.clear() self.model.msg_view.extend(w_list) self.model.msg_list.set_focus(focus_msg)
def narrow_to_user(self, button: Any) -> None: if self.model.narrow == [["pm_with", button.email]]: return self.update = False self.model.narrow = [["pm_with", button.email]] msg_id_list = self.model.index['private'].get(frozenset( [self.model.user_id, button.user_id]), []) self.model.num_after = 10 self.model.num_before = 30 if hasattr(button, 'message'): self.model.anchor = button.message['id'] self.model.get_messages(False) elif len(msg_id_list) == 0: self.model.get_messages(True) recipients = frozenset([self.model.user_id, button.user_id]) self.model.recipients = recipients msg_id_list = self.model.index['private'].get(recipients, []) if hasattr(button, 'message'): w_list = create_msg_box_list( self.model, msg_id_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_id_list) focus_position = self.model.index['pointer'][str(self.model.narrow)] if focus_position == set(): focus_position = len(w_list) - 1 self.model.msg_view.clear() self.model.msg_view.extend(w_list) if focus_position >= 0 and focus_position < len(w_list): self.model.msg_list.set_focus(focus_position)
def narrow_to_topic(self, button: Any) -> None: if self.model.narrow == [['stream', button.caption], ['topic', button.title]]: return self.update = False self.model.stream_id = button.stream_id self.model.narrow = [["stream", button.caption], ["topic", button.title]] msg_id_list = self.model.index['stream'][button.stream_id].get( button.title, []) if len(msg_id_list) == 0: first_anchor = True if hasattr(button, 'message'): self.model.anchor = button.message['id'] first_anchor = False self.model.num_after = 10 self.model.num_before = 30 self.model.get_messages(first_anchor) msg_id_list = self.model.index['stream'][button.stream_id].get( button.title, []) if hasattr(button, 'message'): w_list = create_msg_box_list( self.model, msg_id_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_id_list) focus_position = self.model.index['pointer'][str(self.model.narrow)] if focus_position == set(): focus_position = len(w_list) - 1 self.model.msg_view.clear() self.model.msg_view.extend(w_list) if focus_position >= 0 and focus_position < len(w_list): self.model.msg_list.set_focus(focus_position)
def narrow_to_topic(self, button: Any) -> None: already_narrowed = self.model.set_narrow(stream=button.caption, topic=button.title) if already_narrowed: return self.update = False self.model.stream_id = button.stream_id msg_id_list = self.model.index['stream'][button.stream_id].get( button.title, []) if len(msg_id_list) == 0: get_msg_opts = dict(num_before=30, num_after=10, anchor=None) # type: GetMessagesArgs if hasattr(button, 'message'): get_msg_opts['anchor'] = button.message['id'] self.model.get_messages(**get_msg_opts) msg_id_list = self.model.index['stream'][button.stream_id].get( button.title, []) if hasattr(button, 'message'): w_list = create_msg_box_list(self.model, msg_id_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_id_list) self._finalize_show(w_list)
def narrow_to_stream(self, button: Any) -> None: already_narrowed = self.model.set_narrow(stream=button.caption) if already_narrowed: return self.update = False # store the steam id in the model self.model.stream_id = button.stream_id # get the message ids of the current narrow msg_id_list = self.model.index['all_stream'][button.stream_id] # if no messages are found get more messages if len(msg_id_list) == 0: get_msg_opts = dict(num_before=30, num_after=10, anchor=None) # type: GetMessagesArgs if hasattr(button, 'message'): get_msg_opts['anchor'] = button.message['id'] self.model.get_messages(**get_msg_opts) msg_id_list = self.model.index['all_stream'][button.stream_id] if hasattr(button, 'message'): w_list = create_msg_box_list(self.model, msg_id_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_id_list) self._finalize_show(w_list)
def narrow_to_user(self, button: Any) -> None: if hasattr(button, 'message'): emails = [ recipient['email'] for recipient in button.message['display_recipient'] if recipient['email'] != self.model.client.email ] if not emails and len(button.message['display_recipient']) == 1: emails = [self.model.user_email] user_emails = ', '.join(emails) else: user_emails = button.email already_narrowed = self.model.set_narrow(pm_with=user_emails) if already_narrowed: return self.model.found_newest = False msg_id_list = self.model.get_message_ids_in_current_narrow() if len(msg_id_list) == 0: get_msg_opts = dict(num_before=30, num_after=10, anchor=None) # type: GetMessagesArgs if hasattr(button, 'message'): get_msg_opts['anchor'] = button.message['id'] self.model.get_messages(**get_msg_opts) msg_id_list = self.model.get_message_ids_in_current_narrow() if hasattr(button, 'message'): w_list = create_msg_box_list(self.model, msg_id_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_id_list) self._finalize_show(w_list)
def narrow_to_topic(self, button: Any) -> None: already_narrowed = self.model.set_narrow(stream=button.caption, topic=button.title) if already_narrowed: return self.update = False self.model.stream_id = button.stream_id msg_id_list = self.model.index['stream'][button.stream_id].get( button.title, []) if len(msg_id_list) == 0: first_anchor = True if hasattr(button, 'message'): self.model.anchor = button.message['id'] first_anchor = False self.model.num_after = 10 self.model.num_before = 30 self.model.get_messages(first_anchor) msg_id_list = self.model.index['stream'][button.stream_id].get( button.title, []) if hasattr(button, 'message'): w_list = create_msg_box_list(self.model, msg_id_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_id_list) self._finalize_show(w_list)
def show_all_messages(self, button: Any) -> None: already_narrowed = self.model.set_narrow() if already_narrowed: return self.update = False msg_list = self.model.index['all_messages'] if hasattr(button, 'message'): w_list = create_msg_box_list(self.model, msg_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_list) self._finalize_show(w_list)
def show_all_messages(self, button: Any) -> None: already_narrowed = self.model.set_narrow() if already_narrowed: return self.model.found_newest = False msg_id_list = self.model.get_message_ids_in_current_narrow() if hasattr(button, 'message'): w_list = create_msg_box_list(self.model, msg_id_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_id_list) self._finalize_show(w_list)
def test_create_msg_box_list(mocker, narrow, messages, focus_msg_id, muted, unsubscribed, len_w_list): model = mocker.Mock() model.narrow = narrow model.index = { 'all_msg_ids': {1, 2}, 'messages': { 1: { 'id': 1, 'flags': ['read'], 'timestamp': 10, }, 2: { 'id': 2, 'flags': [], 'timestamp': 10, } }, 'pointer': {}, } msg_box = mocker.patch('zulipterminal.ui_tools.utils.MessageBox') mocker.patch('zulipterminal.ui_tools.utils.urwid.AttrMap', return_value='MSG') mocker.patch('zulipterminal.ui_tools.utils.is_muted', return_value=muted) mocker.patch('zulipterminal.ui_tools.utils.is_unsubscribed_message', return_value=unsubscribed) return_value = create_msg_box_list(model, messages, focus_msg_id=focus_msg_id) assert len(return_value) == len_w_list
def test_create_msg_box_list( mocker, narrow, messages, focus_msg_id, muted, unsubscribed, len_w_list ): model = mocker.Mock() model.narrow = narrow model.index = { "all_msg_ids": {1, 2}, "messages": { 1: { "id": 1, "flags": ["read"], "timestamp": 10, }, 2: { "id": 2, "flags": [], "timestamp": 10, }, }, "pointer": {}, } msg_box = mocker.patch("zulipterminal.ui_tools.utils.MessageBox") mocker.patch("zulipterminal.ui_tools.utils.urwid.AttrMap", return_value="MSG") mock_muted = mocker.patch( "zulipterminal.ui_tools.utils.is_muted", return_value=muted ) mocker.patch( "zulipterminal.ui_tools.utils.is_unsubscribed_message", return_value=unsubscribed, ) return_value = create_msg_box_list(model, messages, focus_msg_id=focus_msg_id) assert len(return_value) == len_w_list assert mock_muted.called is not unsubscribed
def main_view(self) -> List[Any]: msg_btn_list = create_msg_box_list(self.model) focus_msg = self.model.index['pointer'][str(self.model.narrow)] if focus_msg == set(): focus_msg = len(msg_btn_list) - 1 self.focus_msg = focus_msg return msg_btn_list
def narrow_to_user(self, button: Any) -> None: if self.model.narrow == [["pm_with", button.email]]: return if hasattr(button, 'message'): if self.model.narrow == []: self.model.focus_all_msg = button.message['id'] self.model.narrow = [["pm_with", button.email]] self.model.num_after = 10 self.model.num_before = 30 classified_msgs = self.model.load_old_messages(True) messages = classified_msgs[button.email] if len(messages) < 41: self.model.update = True if len(messages) == 0: messages = [{ 'content': ' No Messages yet! Why not start the conversation?', 'title': '', 'type': 'private', 'time': 0, 'sender': '', 'stream': '', 'sender_email': button.email, 'id': 10000000000, 'color': None, }] w_list, focus_msg = create_msg_box_list(messages, self.model, narrow=True) self.model.msg_view.clear() self.model.msg_view.extend(w_list) self.model.msg_list.set_focus(focus_msg)
def _narrow_to(self, button: Any, anchor: Optional[int], **narrow: Any) -> None: already_narrowed = self.model.set_narrow(**narrow) if already_narrowed: return # store the steam id in the model (required for get_message_ids...) if hasattr(button, 'stream_id'): # FIXME Include in set_narrow? self.model.stream_id = button.stream_id msg_id_list = self.model.get_message_ids_in_current_narrow() # if no messages are found get more messages if len(msg_id_list) == 0: self.model.get_messages(num_before=30, num_after=10, anchor=anchor) msg_id_list = self.model.get_message_ids_in_current_narrow() w_list = create_msg_box_list(self.model, msg_id_list, focus_msg_id=anchor) focus_position = self.model.get_focus_in_current_narrow() if focus_position == set(): # No available focus; set to end focus_position = len(w_list) - 1 assert not isinstance(focus_position, set) self.view.message_view.log.clear() if 0 <= focus_position < len(w_list): self.view.message_view.log.extend(w_list, focus_position) else: self.view.message_view.log.extend(w_list) self.exit_editor_mode()
def load_old_messages(self, anchor: int = 10000000000) -> None: self.old_loading = True ids_to_keep = self.model.get_message_ids_in_current_narrow() if self.log: top_message_id = self.log[0].original_widget.message['id'] ids_to_keep.remove(top_message_id) # update this id no_update_baseline = {top_message_id} else: no_update_baseline = set() self.model.get_messages(num_before=30, num_after=0, anchor=anchor) ids_to_process = (self.model.get_message_ids_in_current_narrow() - ids_to_keep) # Only update if more messages are provided if ids_to_process != no_update_baseline: if self.log: self.log.remove(self.log[0]) # avoid duplication when updating message_list = create_msg_box_list(self.model, ids_to_process) message_list.reverse() for msg_w in message_list: self.log.insert(0, msg_w) self.set_focus(self.focus_msg) # Return focus to original message self.model.controller.update_screen() self.old_loading = False
def narrow_to_stream(self, button: Any) -> None: # return if already narrowed if self.model.narrow == [['stream', button.caption]]: return self.update = False # store the steam id in the model self.model.stream_id = button.stream_id # set the current narrow self.model.narrow = [['stream', button.caption]] # get the message ids of the current narrow msg_id_list = self.model.index['all_stream'][button.stream_id] # if no messages are found get more messages if len(msg_id_list) == 0: self.model.num_after = 10 self.model.num_before = 30 if hasattr(button, 'message'): self.model.anchor = button.message['id'] self.model.get_messages(False) else: self.model.get_messages(True) msg_id_list = self.model.index['all_stream'][button.stream_id] w_list = create_msg_box_list(self.model, msg_id_list) focus_position = self.model.index['pointer'][str(self.model.narrow)] if focus_position == set(): focus_position = len(w_list) - 1 self.model.msg_view.clear() self.model.msg_view.extend(w_list) if focus_position >= 0 and focus_position < len(w_list): self.model.msg_list.set_focus(focus_position)
def main_view(self) -> List[Any]: msg_btn_list = create_msg_box_list(self.model) focus_msg = self.model.get_focus_in_current_narrow() if focus_msg == set(): focus_msg = len(msg_btn_list) - 1 self.focus_msg = focus_msg return msg_btn_list
def _narrow_to(self, anchor: Optional[int], **narrow: Any) -> None: already_narrowed = self.model.set_narrow(**narrow) if already_narrowed: return msg_id_list = self.model.get_message_ids_in_current_narrow() # if no messages are found get more messages if len(msg_id_list) == 0: self.model.get_messages(num_before=30, num_after=10, anchor=anchor) msg_id_list = self.model.get_message_ids_in_current_narrow() w_list = create_msg_box_list(self.model, msg_id_list, focus_msg_id=anchor) focus_position = self.model.get_focus_in_current_narrow() if focus_position == set(): # No available focus; set to end focus_position = len(w_list) - 1 assert not isinstance(focus_position, set) self.view.message_view.log.clear() if 0 <= focus_position < len(w_list): self.view.message_view.log.extend(w_list, focus_position) else: self.view.message_view.log.extend(w_list) self.exit_editor_mode()
def update_reaction(self, response: Dict[str, Any]) -> None: message_id = response['message_id'] # If the message is indexed if self.index['messages'][message_id] != {}: message = self.index['messages'][message_id] if response['op'] == 'add': message['reactions'].append( { 'user': response['user'], 'reaction_type': response['reaction_type'], 'emoji_code': response['emoji_code'], 'emoji_name': response['emoji_name'], } ) else: emoji_code = response['emoji_code'] for reaction in message['reactions']: # Since Who reacted is not displayed, # remove the first one encountered if reaction['emoji_code'] == emoji_code: message['reactions'].remove(reaction) self.index['messages'][message_id] = message # Update new content in the rendered view for msg_w in self.msg_list.log: if msg_w.original_widget.message['id'] == message_id: new_msg_w = create_msg_box_list(self, [message_id])[0] msg_pos = self.msg_list.log.index(msg_w) self.msg_list.log[msg_pos] = new_msg_w self.controller.loop.draw_screen()
def append_message(self, response: Dict[str, Any]) -> None: """ Adds message to the end of the view. """ response['flags'] = [] if hasattr(self.controller, 'view') and self.update: self.index = index_messages([response], self, self.index) msg_w = create_msg_box_list(self, [response['id']])[0] if self.narrow == []: self.msg_list.log.append(msg_w) elif self.narrow[0][1] == response['type'] and\ len(self.narrow) == 1: self.msg_list.log.append(msg_w) elif response['type'] == 'stream' and len(self.narrow) == 2 and\ self.narrow[1][1] == response['subject']: self.msg_list.log.append(msg_w) elif response['type'] == 'private' and len(self.narrow) == 1 and\ self.narrow[0][0] == "pm_with": recipients = self.recipients msg_recipients = frozenset([ self.user_id, self.user_dict[self.narrow[0][1]]['user_id'] ]) if recipients == msg_recipients: self.msg_list.log.append(msg_w) set_count([response['id']], self.controller, 1) self.controller.loop.draw_screen()
def _narrow_to(self, button: Any, anchor: Optional[int], **narrow: Any) -> None: already_narrowed = self.model.set_narrow(**narrow) if already_narrowed: return self.model.found_newest = False # store the steam id in the model (required for get_message_ids...) if hasattr(button, 'stream_id'): # FIXME Include in set_narrow? self.model.stream_id = button.stream_id msg_id_list = self.model.get_message_ids_in_current_narrow() # if no messages are found get more messages if len(msg_id_list) == 0: self.model.get_messages(num_before=30, num_after=10, anchor=anchor) msg_id_list = self.model.get_message_ids_in_current_narrow() w_list = create_msg_box_list(self.model, msg_id_list, focus_msg_id=anchor) self._finalize_show(w_list)
def _update_rendered_view(self, msg_id: int) -> None: """ Helper method called by various _handle_* methods """ # Update new content in the rendered view view = self.controller.view for msg_w in view.message_view.log: msg_box = msg_w.original_widget if msg_box.message['id'] == msg_id: # Remove the message if it no longer belongs in the current # narrow. if (len(self.narrow) == 2 and msg_box.message['subject'] != self.narrow[1][1]): view.message_view.log.remove(msg_w) # Change narrow if there are no messages left in the # current narrow. if not view.message_view.log: msg_w_list = create_msg_box_list( self, [msg_id], last_message=msg_box.last_message) if msg_w_list: self.controller.narrow_to_topic( msg_w_list[0].original_widget) self.controller.update_screen() return msg_w_list = create_msg_box_list( self, [msg_id], last_message=msg_box.last_message) if not msg_w_list: return else: new_msg_w = msg_w_list[0] msg_pos = view.message_view.log.index(msg_w) view.message_view.log[msg_pos] = new_msg_w # If this is not the last message in the view # update the next message's last_message too. if len(view.message_view.log) != (msg_pos + 1): next_msg_w = view.message_view.log[msg_pos + 1] msg_w_list = create_msg_box_list( self, [next_msg_w.original_widget.message['id']], last_message=new_msg_w.original_widget.message) view.message_view.log[msg_pos + 1] = msg_w_list[0] self.controller.update_screen() return
def show_all_messages(self, button: Any) -> None: self.model.msg_view.clear() msg_list = itertools.chain.from_iterable(self.model.messages.values()) w_list, focus_msg = create_msg_box_list(msg_list, self.model) if hasattr(button, 'message') and self.model.narrow != []: focus_msg += 1 self.model.msg_view.extend(w_list) self.model.msg_list.set_focus(focus_msg) self.model.narrow = []
def load_new_messages(self, anchor: int) -> None: self.new_loading = True current_ids = self.model.get_message_ids_in_current_narrow() self.index = self.model.get_messages(num_before=0, num_after=30, anchor=anchor) msg_ids = self.model.get_message_ids_in_current_narrow() - current_ids message_list = create_msg_box_list(self.model, msg_ids) self.log.extend(message_list) self.model.controller.update_screen() self.new_loading = False
def narrow_to_stream(self, button: Any) -> None: if self.model.narrow == [['stream', button.caption]]: return if hasattr(button, 'message') and self.model.narrow == []: self.model.focus_all_msg = button.message['id'] self.model.narrow = [['stream', button.caption]] self.model.num_after = 10 self.model.num_before = 30 if hasattr(button, 'message'): self.model.anchor = button.message['id'] classified_msgs = self.model.load_old_messages(False) else: classified_msgs = self.model.load_old_messages(True) messages = classified_msgs[button.stream_id] if len(messages) < 41: self.model.update = True # FIXME EMPTY `messages` on old streams with no new messages if len(messages) == 0: messages = [{ 'content': ' No Messages yet! Why not start the conversation?', 'title': '', 'type': 'stream', 'time': 0, 'sender': '', 'stream': button.caption, 'sender_email': '', 'id': 10000000000, 'color': None, 'stream_id': button.stream_id, }] if hasattr(button, 'message'): w_list, focus_msg = create_msg_box_list(messages, self.model, narrow=True, id=button.message['id']) focus_msg += 1 else: w_list, focus_msg = create_msg_box_list(messages, self.model, narrow=True) self.model.msg_view.clear() self.model.msg_view.extend(w_list) self.model.msg_list.set_focus(focus_msg)
def test_create_msg_box_list(mocker, narrow, index, messages, focus_msg_id, muted, len_w_list): model = mocker.Mock() model.narrow = narrow model.index = index msg_box = mocker.patch('zulipterminal.ui_tools.utils.MessageBox') mocker.patch('zulipterminal.ui_tools.utils.urwid.AttrMap', return_value='MSG') mocker.patch('zulipterminal.ui_tools.utils.is_muted', return_value=muted) return_value = create_msg_box_list(model, messages, focus_msg_id) assert len(return_value) == len_w_list
def narrow_to_user(self, button: Any) -> None: if hasattr(button, 'message'): emails = [ recipient['email'] for recipient in button.message['display_recipient'] if recipient['email'] != self.model.client.email ] user_emails = ', '.join(emails) user_ids = { user['id'] for user in button.message['display_recipient'] } else: user_emails = button.email user_ids = {self.model.user_id, button.user_id} already_narrowed = self.model.set_narrow(pm_with=user_emails) if already_narrowed: return self.update = False recipients = frozenset(user_ids) # store the recipients in the model (required for get_message_ids...) self.model.recipients = recipients msg_id_list = self.model.get_message_ids_in_current_narrow() if len(msg_id_list) == 0: get_msg_opts = dict(num_before=30, num_after=10, anchor=None) # type: GetMessagesArgs if hasattr(button, 'message'): get_msg_opts['anchor'] = button.message['id'] self.model.get_messages(**get_msg_opts) msg_id_list = self.model.get_message_ids_in_current_narrow() if hasattr(button, 'message'): w_list = create_msg_box_list(self.model, msg_id_list, button.message['id']) else: w_list = create_msg_box_list(self.model, msg_id_list) self._finalize_show(w_list)
def update_rendered_view(self, msg_id: int) -> None: # Update new content in the rendered view for msg_w in self.msg_list.log: if msg_w.original_widget.message['id'] == msg_id: msg_w_list = create_msg_box_list(self, [msg_id]) if not msg_w_list: return else: new_msg_w = msg_w_list[0] msg_pos = self.msg_list.log.index(msg_w) self.msg_list.log[msg_pos] = new_msg_w self.controller.update_screen()
def load_new_messages(self, anchor: int, focus_position: int) -> None: self.new_loading = True self.model.anchor = anchor self.model.num_before = 0 self.model.num_after = 30 current_ids = self.get_current_ids() self.index = self.model.get_messages(False) msg_ids = self.get_current_ids() - current_ids message_list = create_msg_box_list(self.model, msg_ids) self.log.extend(message_list) self.model.controller.loop.draw_screen() self.new_loading = False