Skip to content

Commit 6e06ef0

Browse files
committed
streams: Handle remove stream events.
1 parent 04a5408 commit 6e06ef0

File tree

6 files changed

+136
-8
lines changed

6 files changed

+136
-8
lines changed

tests/model/test_model.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,6 +1843,78 @@ def test__handle_subscription_event_add_stream(
18431843
update_left_panel.assert_called_once_with()
18441844
model.controller.update_screen.assert_called_once_with()
18451845

1846+
@pytest.mark.parametrize(['event', 'expected_pinned_streams',
1847+
'expected_unpinned_streams'], [
1848+
(
1849+
{
1850+
'op': 'remove',
1851+
'subscriptions': [{
1852+
'name': 'design',
1853+
'stream_id': 2
1854+
}]
1855+
},
1856+
[],
1857+
[{
1858+
'name': 'all',
1859+
'id': 4,
1860+
'color': '#48e',
1861+
'invite_only': False,
1862+
'description': ''
1863+
}]
1864+
),
1865+
(
1866+
{
1867+
'op': 'remove',
1868+
'subscriptions': [{
1869+
'name': 'all',
1870+
'stream_id': 4
1871+
}]
1872+
},
1873+
[{
1874+
'name': 'design',
1875+
'id': 2,
1876+
'color': '#48e',
1877+
'invite_only': False,
1878+
'description': ''
1879+
}],
1880+
[]
1881+
)], ids=[
1882+
'remove_2',
1883+
'remove_4'
1884+
]
1885+
)
1886+
def test__handle_subscription_event_remove_stream(
1887+
self, model, mocker,
1888+
event,
1889+
expected_pinned_streams,
1890+
expected_unpinned_streams,
1891+
initial_pinned_streams=[{
1892+
'name': 'design',
1893+
'id': 2,
1894+
'color': '#48e',
1895+
'invite_only': False,
1896+
'description': ''
1897+
}],
1898+
initial_unpinned_streams=[{
1899+
'name': 'all',
1900+
'id': 4,
1901+
'color': '#48e',
1902+
'invite_only': False,
1903+
'description': ''
1904+
}]
1905+
):
1906+
1907+
model.pinned_streams = deepcopy(initial_pinned_streams)
1908+
model.unpinned_streams = deepcopy(initial_unpinned_streams)
1909+
1910+
model._handle_subscription_event(event)
1911+
1912+
assert model.pinned_streams == expected_pinned_streams
1913+
assert model.unpinned_streams == expected_unpinned_streams
1914+
update_left_panel = model.controller.view.left_panel.update_stream_view
1915+
update_left_panel.assert_called_once_with()
1916+
model.controller.update_screen.assert_called_once_with()
1917+
18461918
@pytest.mark.parametrize(['event', 'feature_level',
18471919
'stream_id', 'expected_subscribers'], [
18481920
({'op': 'peer_add', 'stream_id': 99, 'user_id': 12}, None,

tests/ui/test_ui_tools.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def mock_external_classes(self, mocker):
7474
self.model = mocker.MagicMock()
7575
self.view = mocker.Mock()
7676
self.urwid = mocker.patch(VIEWS + ".urwid")
77+
self.model.is_user_view_in_removed_stream.return_value = False
7778

7879
@pytest.fixture
7980
def msg_view(self, mocker, msg_box):
@@ -811,6 +812,7 @@ def mock_external_classes(self, mocker):
811812
self.super = mocker.patch(VIEWS + '.urwid.Frame.__init__')
812813
self.super_keypress = mocker.patch(VIEWS + '.urwid.Frame.keypress')
813814
self.model.controller == mocker.Mock()
815+
self.model.is_user_view_in_removed_stream.return_value = False
814816

815817
@pytest.fixture
816818
def mid_col_view(self):
@@ -1259,6 +1261,7 @@ class TestMessageBox:
12591261
def mock_external_classes(self, mocker, initial_index):
12601262
self.model = mocker.MagicMock()
12611263
self.model.index = initial_index
1264+
self.model.is_user_view_in_removed_stream.return_value = False
12621265

12631266
@pytest.mark.parametrize('message_type, set_fields', [
12641267
('stream',

tests/ui_tools/test_boxes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class TestWriteBox:
1414
def mock_external_classes(self, mocker, initial_index):
1515
self.view = mocker.Mock()
1616
self.view.model = mocker.Mock()
17+
self.view.model.is_user_view_in_removed_stream.return_value = False
1718

1819
@pytest.fixture()
1920
def write_box(self, mocker, users_fixture, user_groups_fixture,

zulipterminal/model.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,15 @@ def toggle_stream_pinned_status(self, stream_id: int) -> bool:
730730
def is_user_subscribed_to_stream(self, stream_id: int) -> bool:
731731
return stream_id in self.stream_dict
732732

733+
def is_user_view_in_removed_stream(self, stream_id: int) -> bool:
734+
for stream in self.pinned_streams:
735+
if stream['id'] == stream_id:
736+
return False
737+
for stream in self.unpinned_streams:
738+
if stream['id'] == stream_id:
739+
return False
740+
return True
741+
733742
def _handle_subscription_event(self, event: Event) -> None:
734743
"""
735744
Handle changes in subscription (eg. muting/unmuting,
@@ -805,6 +814,21 @@ def make_reduced_stream_data(stream: Any) -> StreamData:
805814
self.controller.view.left_panel.update_stream_view()
806815
self.controller.update_screen()
807816

817+
elif event['op'] == 'remove':
818+
for stream_info in event['subscriptions']:
819+
stream_id = stream_info['stream_id']
820+
try:
821+
stream = get_stream_by_id(self.pinned_streams,
822+
stream_id)
823+
self.pinned_streams.remove(stream)
824+
except RuntimeError:
825+
stream = get_stream_by_id(self.unpinned_streams,
826+
stream_id)
827+
self.unpinned_streams.remove(stream)
828+
829+
self.controller.view.left_panel.update_stream_view()
830+
self.controller.update_screen()
831+
808832
elif event['op'] in ('peer_add', 'peer_remove'):
809833
# NOTE: ZFL 35 commit was not atomic with API change
810834
# (ZFL >=35 can use new plural style)

zulipterminal/ui_tools/boxes.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ def private_box_view(self, button: Any=None, email: str='',
7777

7878
def stream_box_view(self, stream_id: int, caption: str='', title: str='',
7979
) -> None:
80+
if(self.model.is_user_view_in_removed_stream(stream_id)):
81+
self.model.controller.view.set_footer_text(
82+
" You can't reply to messages from unsubscribed streams.", 3)
83+
return
8084
self.set_editor_mode()
8185
self.stream_id = stream_id
8286
self.recipient_user_ids = self.model.get_other_subscribers_in_stream(
@@ -1133,6 +1137,11 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
11331137
stream_id=self.stream_id,
11341138
)
11351139
elif is_command_key('STREAM_MESSAGE', key):
1140+
if(self.model.is_user_view_in_removed_stream(self.stream_id)):
1141+
self.model.controller.view.set_footer_text(
1142+
" You can't write messages from unsubscribed streams.",
1143+
3)
1144+
return None
11361145
if self.message['type'] == 'private':
11371146
self.model.controller.view.write_box.private_box_view(
11381147
email=self.recipients_emails,
@@ -1177,13 +1186,18 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
11771186
recipient_user_ids=[self.message['sender_id']],
11781187
)
11791188
elif is_command_key('MENTION_REPLY', key):
1180-
self.keypress(size, 'enter')
1181-
mention = '@**' + self.message['sender_full_name'] + '** '
1182-
self.model.controller.view.write_box.msg_write_box.set_edit_text(
1183-
mention)
1184-
self.model.controller.view.write_box.msg_write_box.set_edit_pos(
1185-
len(mention))
1186-
self.model.controller.view.middle_column.set_focus('footer')
1189+
if(not self.model.is_user_view_in_removed_stream(self.stream_id)):
1190+
self.keypress(size, 'enter')
1191+
mention = '@**' + self.message['sender_full_name'] + '** '
1192+
write_box = self.model.controller.view.write_box.msg_write_box
1193+
write_box.set_edit_text(mention)
1194+
write_box.set_edit_pos(len(mention))
1195+
self.model.controller.view.middle_column.set_focus('footer')
1196+
else:
1197+
self.model.controller.view.set_footer_text(
1198+
" You can't reply to messages from unsubscribed streams.",
1199+
3)
1200+
return key
11871201
elif is_command_key('QUOTE_REPLY', key):
11881202
self.keypress(size, 'enter')
11891203
quote = '```quote\n' + self.model.client.get_raw_message(
@@ -1194,6 +1208,11 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
11941208
len(quote))
11951209
self.model.controller.view.middle_column.set_focus('footer')
11961210
elif is_command_key('EDIT_MESSAGE', key):
1211+
if(self.model.is_user_view_in_removed_stream(self.stream_id)):
1212+
self.model.controller.view.set_footer_text(
1213+
" You can't edit messages from unsubscribed streams.",
1214+
3)
1215+
return key
11971216
if self.message['sender_id'] != self.model.user_id:
11981217
self.model.controller.view.set_footer_text(
11991218
" You can't edit messages sent by other users.", 3)

zulipterminal/ui_tools/views.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,13 +538,22 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]:
538538
return key
539539

540540
elif is_command_key('STREAM_MESSAGE', key):
541+
if(self.model.is_user_view_in_removed_stream(
542+
self.model.stream_id)):
543+
self.model.controller.view.set_footer_text(
544+
" You can't write messages from unsubscribed streams.",
545+
3)
546+
return None
541547
self.body.keypress(size, 'c')
548+
542549
# For new streams with no previous conversation.
543550
if self.footer.focus is None:
544551
stream_id = self.model.stream_id
545552
stream_dict = self.model.stream_dict
546553
self.footer.stream_box_view(
547-
caption=stream_dict[stream_id]['name'])
554+
caption=stream_dict[stream_id]['name'],
555+
stream_id=stream_id
556+
)
548557
self.set_focus('footer')
549558
self.footer.focus_position = 0
550559
return key

0 commit comments

Comments
 (0)