Skip to content

Commit 3347988

Browse files
zee-bitneiljp
authored andcommitted
buttons/views: Display and sort emojis by count in EmojiPicker view.
A new reaction_count field is added to the EmojiButton class to keep in check the number of reactions with a particular emoji on a message. The EmojiPicker view also shows the count of reactions of a particular emoji beside emoji_name, and the list is sorted in descending order of emoji_count, then in ascending order of emoji_names if the count is equal. Tests amended.
1 parent d3003fb commit 3347988

File tree

3 files changed

+51
-11
lines changed

3 files changed

+51
-11
lines changed

tests/ui_tools/test_buttons.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,16 +228,18 @@ def test_keypress_USER_INFO(
228228

229229
class TestEmojiButton:
230230
@pytest.mark.parametrize(
231-
"emoji_unit, to_vary_in_message",
231+
"emoji_unit, to_vary_in_message, count",
232232
[
233233
case(
234234
("working_on_it", "1f6e0", ["hammer_and_wrench", "tools"]),
235235
{"reactions": [{"emoji_name": "thumbs_up", "user": [{"id": 232}]}]},
236+
0,
236237
id="emoji_button_with_no_reaction",
237238
),
238239
case(
239240
("+1", "1f44d", ["thumbs_up", "like"]),
240241
{"reactions": [{"emoji_name": "+1", "user": [{"id": 10}]}]},
242+
1,
241243
id="emoji_button_with_a_reaction",
242244
),
243245
],
@@ -248,9 +250,11 @@ def test_init_calls_top_button(
248250
emoji_unit: Tuple[str, str, List[str]],
249251
to_vary_in_message: Dict[str, Any],
250252
message_fixture: Message,
253+
count: int,
251254
) -> None:
252255
controller = mocker.Mock()
253256
controller.model.has_user_reacted_to_message = mocker.Mock(return_value=False)
257+
update_widget = mocker.patch(MODULE + ".EmojiButton.update_widget")
254258
top_button = mocker.patch(MODULE + ".TopButton.__init__")
255259
caption = ", ".join([emoji_unit[0], *emoji_unit[2]])
256260
message_fixture["reactions"] = to_vary_in_message["reactions"]
@@ -259,6 +263,7 @@ def test_init_calls_top_button(
259263
controller=controller,
260264
emoji_unit=emoji_unit,
261265
message=message_fixture,
266+
reaction_count=count,
262267
is_selected=lambda *_: False,
263268
toggle_selection=lambda *_: None,
264269
)
@@ -270,15 +275,16 @@ def test_init_calls_top_button(
270275
show_function=emoji_button.update_emoji_button,
271276
)
272277
assert emoji_button.emoji_name == emoji_unit[0]
278+
assert emoji_button.reaction_count == count
273279

274280
@pytest.mark.parametrize("key", keys_for_command("ENTER"))
275281
@pytest.mark.parametrize(
276-
"emoji, has_user_reacted, is_selected_final",
282+
"emoji, has_user_reacted, is_selected_final, expected_reaction_count",
277283
[
278-
case(("smile", "1f642", []), True, False, id="reacted_unselected_emoji"),
279-
case(("smile", "1f642", []), True, True, id="reacted_selected_emoji"),
280-
case(("+1", "1f44d", []), False, False, id="unreacted_unselected_emoji"),
281-
case(("+1", "1f44d", []), False, True, id="unreacted_selected_emoji"),
284+
case(("smile", "1f642", []), True, False, 2, id="reacted_unselected_emoji"),
285+
case(("smile", "1f642", []), True, True, 0, id="reacted_selected_emoji"),
286+
case(("+1", "1f44d", []), False, False, 0, id="unreacted_unselected_emoji"),
287+
case(("+1", "1f44d", []), False, True, 2, id="unreacted_selected_emoji"),
282288
],
283289
)
284290
def test_keypress_emoji_button(
@@ -290,6 +296,7 @@ def test_keypress_emoji_button(
290296
is_selected_final: bool,
291297
widget_size: Callable[[Widget], urwid_Size],
292298
message_fixture: Message,
299+
expected_reaction_count: int,
293300
) -> None:
294301
controller = mocker.Mock()
295302
controller.model.has_user_reacted_to_message = mocker.Mock(
@@ -307,15 +314,23 @@ def test_keypress_emoji_button(
307314
controller=controller,
308315
emoji_unit=emoji,
309316
message=message_fixture,
317+
reaction_count=1,
310318
is_selected=lambda *_: is_selected_final,
311319
toggle_selection=lambda *_: None,
312320
)
313321
size = widget_size(emoji_button)
314322

315323
emoji_button.keypress(size, key)
316324

317-
suffix_text = f"{CHECK_MARK}" if has_user_reacted != is_selected_final else ""
325+
reaction_count = emoji_button.reaction_count
326+
reaction_count_text = "" if reaction_count == 0 else f"{reaction_count}"
327+
suffix_text = (
328+
f"{CHECK_MARK} " + reaction_count_text
329+
if has_user_reacted != is_selected_final
330+
else reaction_count_text
331+
)
318332
assert emoji_button.emoji_name == emoji[0]
333+
assert reaction_count == expected_reaction_count
319334
assert emoji_button.button_suffix.get_text()[0].strip() == suffix_text
320335

321336

zulipterminal/ui_tools/buttons.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,12 +328,14 @@ def __init__(
328328
controller: Any,
329329
emoji_unit: Tuple[str, str, List[str]], # (emoji_name, emoji_code, aliases)
330330
message: Message,
331+
reaction_count: int = 0,
331332
is_selected: Callable[[str], bool],
332333
toggle_selection: Callable[[str, str], None],
333334
) -> None:
334335
self.controller = controller
335336
self.message = message
336337
self.is_selected = is_selected
338+
self.reaction_count = reaction_count
337339
self.toggle_selection = toggle_selection
338340
self.emoji_name, self.emoji_code, self.aliases = emoji_unit
339341
full_button_caption = ", ".join([self.emoji_name, *self.aliases])
@@ -344,20 +346,31 @@ def __init__(
344346
prefix_character="",
345347
show_function=self.update_emoji_button,
346348
)
347-
if self._has_user_reacted_to_msg() or is_selected(self.emoji_name):
348-
self.update_widget((None, f" {CHECK_MARK} "), None)
349+
350+
has_check_mark = self._has_user_reacted_to_msg() or is_selected(self.emoji_name)
351+
self.update_widget((None, self.get_update_widget_text(has_check_mark)), None)
349352

350353
def _has_user_reacted_to_msg(self) -> bool:
351354
return self.controller.model.has_user_reacted_to_message(
352355
self.message, emoji_code=self.emoji_code
353356
)
354357

358+
def get_update_widget_text(self, user_reacted: bool) -> str:
359+
count_text = str(self.reaction_count) if self.reaction_count > 0 else ""
360+
reacted_check_mark = CHECK_MARK if user_reacted else ""
361+
return f" {reacted_check_mark} {count_text} "
362+
355363
def update_emoji_button(self) -> None:
356364
self.toggle_selection(self.emoji_code, self.emoji_name)
357365
is_reaction_added = self._has_user_reacted_to_msg() != self.is_selected(
358366
self.emoji_name
359367
)
360-
self.update_widget((None, f" {CHECK_MARK} " if is_reaction_added else ""), None)
368+
self.reaction_count = (
369+
(self.reaction_count + 1)
370+
if is_reaction_added
371+
else (self.reaction_count - 1)
372+
)
373+
self.update_widget((None, self.get_update_widget_text(is_reaction_added)), None)
361374

362375

363376
class DecodedStream(TypedDict):

zulipterminal/ui_tools/views.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2008,19 +2008,31 @@ def add_or_remove_selected_emoji(self, emoji_code: str, emoji_name: str) -> None
20082008
else:
20092009
self.selected_emojis.update({emoji_code: emoji_name})
20102010

2011+
def count_reactions(self, emoji_code: str) -> int:
2012+
num_reacts = 0
2013+
for reaction in self.message["reactions"]:
2014+
if reaction["emoji_code"] == emoji_code:
2015+
num_reacts += 1
2016+
return num_reacts
2017+
20112018
def generate_emoji_buttons(
20122019
self, emoji_units: List[Tuple[str, str, List[str]]]
20132020
) -> List[EmojiButton]:
2014-
return [
2021+
emoji_buttons = [
20152022
EmojiButton(
20162023
controller=self.controller,
20172024
emoji_unit=emoji_unit,
20182025
message=self.message,
2026+
reaction_count=self.count_reactions(emoji_unit[1]),
20192027
is_selected=self.is_selected_emoji,
20202028
toggle_selection=self.add_or_remove_selected_emoji,
20212029
)
20222030
for emoji_unit in emoji_units
20232031
]
2032+
sorted_emoji_buttons = sorted(
2033+
emoji_buttons, key=lambda button: button.reaction_count, reverse=True
2034+
)
2035+
return sorted_emoji_buttons
20242036

20252037
def keypress(self, size: urwid_Size, key: str) -> str:
20262038
if (

0 commit comments

Comments
 (0)