Skip to content

Commit f00bfb8

Browse files
Rohitth007neiljp
authored andcommitted
ui: Add TabView's to autohide layout.
This commit adds a closed tab view of width 3 for each of the side panels when in the autohide layout. The initial layout when the app is started is left panel open, right panel closed. This makes use of the TabView class and changes show_left_panel and show_right_panel accordingly. Tests updated.
1 parent 7270d46 commit f00bfb8

File tree

3 files changed

+57
-23
lines changed

3 files changed

+57
-23
lines changed

tests/ui/test_ui.py

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from zulipterminal.api_types import Composition
88
from zulipterminal.config.keys import keys_for_command
9-
from zulipterminal.ui import LEFT_WIDTH, RIGHT_WIDTH, View
9+
from zulipterminal.ui import LEFT_WIDTH, RIGHT_WIDTH, TAB_WIDTH, View
1010
from zulipterminal.urwid_types import urwid_Box
1111

1212

@@ -25,9 +25,15 @@ def mock_external_classes(self, mocker: MockerFixture) -> None:
2525

2626
@pytest.fixture
2727
def view(self, mocker: MockerFixture) -> View:
28-
main_window = mocker.patch(VIEW + ".main_window")
28+
mocker.patch(MODULE + ".TabView")
29+
mocker.patch(MODULE + ".LeftColumnView")
30+
mocker.patch("zulipterminal.ui_tools.views.urwid.Frame")
31+
mocker.patch("zulipterminal.ui_tools.views.MessageView")
32+
mocker.patch(MODULE + ".RightColumnView")
33+
2934
# View is an urwid.Frame instance, a Box widget.
3035
mocker.patch(VIEW + ".sizing", return_value=frozenset({"box"}))
36+
3137
return View(self.controller)
3238

3339
def test_init(self, mocker: MockerFixture) -> None:
@@ -44,8 +50,11 @@ def test_init(self, mocker: MockerFixture) -> None:
4450

4551
def test_left_column_view(self, mocker: MockerFixture, view: View) -> None:
4652
left_view = mocker.patch(MODULE + ".LeftColumnView")
53+
left_tab = mocker.patch(MODULE + ".TabView")
54+
4755
return_value = view.left_column_view()
48-
assert return_value == left_view(view)
56+
57+
assert return_value == (left_view(view), left_tab())
4958

5059
def test_middle_column_view(self, view: View, mocker: MockerFixture) -> None:
5160
middle_view = mocker.patch(MODULE + ".MiddleColumnView")
@@ -59,11 +68,14 @@ def test_middle_column_view(self, view: View, mocker: MockerFixture) -> None:
5968

6069
def test_right_column_view(self, view: View, mocker: MockerFixture) -> None:
6170
right_view = mocker.patch(MODULE + ".RightColumnView")
71+
right_tab = mocker.patch(MODULE + ".TabView")
6272
line_box = mocker.patch(MODULE + ".urwid.LineBox")
73+
6374
return_value = view.right_column_view()
75+
6476
right_view.assert_called_once_with(view)
6577
assert view.users_view == right_view()
66-
assert return_value == line_box()
78+
assert return_value == (line_box(), right_tab())
6779

6880
def test_set_footer_text_default(self, view: View, mocker: MockerFixture) -> None:
6981
mocker.patch(VIEW + ".get_random_help", return_value=["some help text"])
@@ -153,15 +165,15 @@ def test_footer_view(self, mocker: MockerFixture, view: View) -> None:
153165
def test_main_window(
154166
self, mocker: MockerFixture, monkeypatch: pytest.MonkeyPatch
155167
) -> None:
156-
left = mocker.patch(VIEW + ".left_column_view")
168+
left = mocker.patch(VIEW + ".left_column_view", return_value=("PANEL", "TAB"))
157169

158170
# NOTE: Use monkeypatch not patch, as view doesn't exist until later
159171
def just_set_message_view(self: Any) -> None:
160172
self.message_view = mocker.Mock(read_message=lambda: None)
161173

162174
monkeypatch.setattr(View, "middle_column_view", just_set_message_view)
163175

164-
right = mocker.patch(VIEW + ".right_column_view")
176+
right = mocker.patch(VIEW + ".right_column_view", return_value=("PANEL", "TAB"))
165177
col = mocker.patch(MODULE + ".urwid.Columns")
166178
frame = mocker.patch(MODULE + ".urwid.Frame")
167179
title_divider = mocker.patch(MODULE + ".urwid.Divider")
@@ -190,9 +202,9 @@ def just_set_message_view(self: Any) -> None:
190202
expected_column_calls = [
191203
mocker.call(
192204
[
193-
(LEFT_WIDTH, left()),
205+
(LEFT_WIDTH, view.left_panel),
194206
("weight", 10, mocker.ANY), # ANY is a center
195-
(0, right()),
207+
(TAB_WIDTH, view.right_tab),
196208
],
197209
focus_column=0,
198210
),
@@ -215,7 +227,7 @@ def just_set_message_view(self: Any) -> None:
215227
)
216228

217229
@pytest.mark.parametrize("autohide", [True, False])
218-
@pytest.mark.parametrize("visible, width", [(True, LEFT_WIDTH), (False, 0)])
230+
@pytest.mark.parametrize("visible, width", [(True, LEFT_WIDTH), (False, TAB_WIDTH)])
219231
def test_show_left_panel(
220232
self,
221233
mocker: MockerFixture,
@@ -224,20 +236,25 @@ def test_show_left_panel(
224236
width: int,
225237
autohide: bool,
226238
) -> None:
227-
view.left_panel = mocker.Mock()
228239
view.body = mocker.Mock()
229-
view.body.contents = [mocker.Mock(), mocker.Mock(), mocker.Mock()]
240+
view.body.contents = [view.left_panel, mocker.Mock(), mocker.Mock()]
230241
view.controller.autohide = autohide
231242

232243
view.show_left_panel(visible=visible)
233244

234245
if autohide:
246+
if visible:
247+
assert view.body.contents[0][0] == view.left_panel
248+
else:
249+
assert view.body.contents[0][0] == view.left_tab
235250
view.body.options.assert_called_once_with("given", width)
236251
else:
237252
view.body.options.assert_not_called()
238253

239254
@pytest.mark.parametrize("autohide", [True, False])
240-
@pytest.mark.parametrize("visible, width", [(True, RIGHT_WIDTH), (False, 0)])
255+
@pytest.mark.parametrize(
256+
"visible, width", [(True, RIGHT_WIDTH), (False, TAB_WIDTH)]
257+
)
241258
def test_show_right_panel(
242259
self,
243260
mocker: MockerFixture,
@@ -246,14 +263,17 @@ def test_show_right_panel(
246263
width: int,
247264
autohide: bool,
248265
) -> None:
249-
view.right_panel = mocker.Mock()
250266
view.body = mocker.Mock()
251-
view.body.contents = [mocker.Mock(), mocker.Mock(), mocker.Mock()]
267+
view.body.contents = [mocker.Mock(), mocker.Mock(), view.right_panel]
252268
view.controller.autohide = autohide
253269

254270
view.show_right_panel(visible=visible)
255271

256272
if autohide:
273+
if visible:
274+
assert view.body.contents[2][0] == view.right_panel
275+
else:
276+
assert view.body.contents[2][0] == view.right_tab
257277
view.body.options.assert_called_once_with("given", width)
258278
else:
259279
view.body.options.assert_not_called()

zulipterminal/config/symbols.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@
1818
STATUS_IDLE = "◒"
1919
STATUS_OFFLINE = "○"
2020
STATUS_INACTIVE = "•"
21+
AUTOHIDE_TAB_LEFT_ARROW = "❰"
22+
AUTOHIDE_TAB_RIGHT_ARROW = "❱"

zulipterminal/ui.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from zulipterminal.config.keys import commands_for_random_tips, is_command_key
99
from zulipterminal.config.symbols import (
1010
APPLICATION_TITLE_BAR_LINE,
11+
AUTOHIDE_TAB_LEFT_ARROW,
12+
AUTOHIDE_TAB_RIGHT_ARROW,
1113
COLUMN_TITLE_BAR_LINE,
1214
)
1315
from zulipterminal.helper import asynch
@@ -17,10 +19,12 @@
1719
LeftColumnView,
1820
MiddleColumnView,
1921
RightColumnView,
22+
TabView,
2023
)
2124
from zulipterminal.urwid_types import urwid_Box
2225

2326

27+
TAB_WIDTH = 3
2428
LEFT_WIDTH = 27
2529
RIGHT_WIDTH = 23
2630

@@ -46,7 +50,11 @@ def __init__(self, controller: Any) -> None:
4650
super().__init__(self.main_window())
4751

4852
def left_column_view(self) -> Any:
49-
return LeftColumnView(self)
53+
tab = TabView(
54+
f"{AUTOHIDE_TAB_LEFT_ARROW} STREAMS & TOPICS {AUTOHIDE_TAB_LEFT_ARROW}"
55+
)
56+
panel = LeftColumnView(self)
57+
return panel, tab
5058

5159
def middle_column_view(self) -> Any:
5260
self.middle_column = MiddleColumnView(
@@ -63,8 +71,9 @@ def middle_column_view(self) -> Any:
6371
)
6472

6573
def right_column_view(self) -> Any:
74+
tab = TabView(f"{AUTOHIDE_TAB_RIGHT_ARROW} USERS {AUTOHIDE_TAB_RIGHT_ARROW}")
6675
self.users_view = RightColumnView(self)
67-
return urwid.LineBox(
76+
panel = urwid.LineBox(
6877
self.users_view,
6978
title="Users",
7079
title_attr="column_title",
@@ -77,6 +86,7 @@ def right_column_view(self) -> Any:
7786
bline="",
7887
brcorner="",
7988
)
89+
return panel, tab
8090

8191
def get_random_help(self) -> List[Any]:
8292
# Get random allowed hotkey (ie. eligible for being displayed as a tip)
@@ -131,14 +141,14 @@ def footer_view(self) -> Any:
131141
return urwid.AttrWrap(urwid.Text(text_header), "footer")
132142

133143
def main_window(self) -> Any:
134-
self.left_panel = self.left_column_view()
144+
self.left_panel, self.left_tab = self.left_column_view()
135145
self.center_panel = self.middle_column_view()
136-
self.right_panel = self.right_column_view()
146+
self.right_panel, self.right_tab = self.right_column_view()
137147
if self.controller.autohide:
138148
body = [
139149
(LEFT_WIDTH, self.left_panel),
140150
("weight", 10, self.center_panel),
141-
(0, self.right_panel),
151+
(TAB_WIDTH, self.right_tab),
142152
]
143153
else:
144154
body = [
@@ -180,15 +190,17 @@ def show_left_panel(self, *, visible: bool) -> None:
180190
if not self.controller.autohide:
181191
return
182192

183-
width = LEFT_WIDTH if visible else 0
184-
self.body.contents[0] = (self.left_panel, self.body.options("given", width))
193+
width = LEFT_WIDTH if visible else TAB_WIDTH
194+
widget = self.left_panel if visible else self.left_tab
195+
self.body.contents[0] = (widget, self.body.options("given", width))
185196

186197
def show_right_panel(self, *, visible: bool) -> None:
187198
if not self.controller.autohide:
188199
return
189200

190-
width = RIGHT_WIDTH if visible else 0
191-
self.body.contents[2] = (self.right_panel, self.body.options("given", width))
201+
width = RIGHT_WIDTH if visible else TAB_WIDTH
202+
widget = self.right_panel if visible else self.right_tab
203+
self.body.contents[2] = (widget, self.body.options("given", width))
192204

193205
def keypress(self, size: urwid_Box, key: str) -> Optional[str]:
194206
self.model.new_user_input = True

0 commit comments

Comments
 (0)