Fix single pane message crash: Refactor message rendering in draw_messages_window and add test for single pane typing behavior

This commit is contained in:
pdxlocations committed 2026-10-19 15:27:40 -07:00
1 parent c956a11672
commit fffc3e3e97
2 files changed
+60 -5

No files matched your search

+8 -5
View File
@@ -1651,14 +1651,17 @@ def draw_messages_window(scroll_to_bottom: bool = False, preserve_selection: boo
return
messages_pad.erase()
# Erasing the pad also removes the old highlight. Its row range may no
# longer exist after switching conversations or rewrapping messages.
ui_state.highlighted_message_range = ()
channel = ui_state.channel_list[ui_state.selected_channel]
msg_line_count = 0
message_ranges = []
rendered_lines = []
if channel in ui_state.all_messages:
messages = ui_state.all_messages[channel]
rendered_lines = []
for prefix, message in messages:
start_line = len(rendered_lines)
full_message = normalize_message_text(f"{prefix}{message}")
@@ -1677,10 +1680,10 @@ def draw_messages_window(scroll_to_bottom: bool = False, preserve_selection: boo
message_ranges.append((start_line, len(rendered_lines), color))
msg_line_count = len(rendered_lines)
messages_pad.resize(max(1, msg_line_count), messages_win.getmaxyx()[1])
for row, (line, color) in enumerate(rendered_lines):
messages_pad.addstr(row, 1, line, color)
ui_state.message_line_ranges[channel] = message_ranges
messages_pad.resize(max(1, msg_line_count), messages_win.getmaxyx()[1])
for row, (line, color) in enumerate(rendered_lines):
messages_pad.addstr(row, 1, line, color)
ui_state.message_line_ranges[channel] = message_ranges
paint_frame(messages_win, selected=(ui_state.current_window == 1), refresh=False)
+52
View File
@@ -214,6 +214,58 @@ class ContactUiTests(unittest.TestCase):
contact_ui.messages_pad.resize.assert_called_once_with(2, 40)
def test_single_pane_typing_after_switching_to_shorter_conversation(self) -> None:
for messages in ([("RX: ", "hello")], [], None):
with self.subTest(messages=messages):
reset_shared_state()
ui_state.single_pane_mode = True
ui_state.current_window = 0
ui_state.channel_list = [123]
ui_state.all_messages = {123: messages} if messages is not None else {}
ui_state.highlighted_message_range = (10, 12, 20)
ui_state.message_line_ranges = {123: [(10, 12, 20)]}
pad = mock.Mock()
pad.getmaxyx.return_value = (12, 40)
def resize_pad(height, width):
pad.getmaxyx.return_value = (height, width)
def change_attributes(row, column, width, color):
height, columns = pad.getmaxyx()
if not (0 <= row < height and 0 <= column < columns and column + width <= columns):
raise contact_ui.curses.error("chgat() returned ERR")
pad.resize.side_effect = resize_pad
pad.chgat.side_effect = change_attributes
win = mock.Mock()
win.getmaxyx.return_value = (10, 40)
packetlog = mock.Mock()
packetlog.getmaxyx.return_value = (1, 40)
with ExitStack() as stack:
for name, value in (("messages_pad", pad), ("messages_win", win), ("packetlog_win", packetlog)):
stack.enter_context(mock.patch.object(contact_ui, name, value, create=True))
for name in ("paint_frame", "refresh_pad", "draw_packetlog_win", "draw_window_arrows", "refresh_main_window"):
stack.enter_context(mock.patch.object(contact_ui, name))
stack.enter_context(mock.patch.object(contact_ui, "get_color", return_value=10))
stack.enter_context(mock.patch.object(
contact_ui, "handle_resize", side_effect=lambda *args: contact_ui.draw_messages_window(True)
))
self.assertEqual(contact_ui.insert_input_text("", "a"), "a")
self.assertEqual(ui_state.current_window, 1)
self.assertTrue(ui_state.input_focused)
self.assertEqual(ui_state.highlighted_message_range, ())
pad.resize.assert_called_once_with(1, 40)
if messages:
self.assertEqual(ui_state.message_line_ranges[123], [(0, 1, 10)])
self.assertEqual(pad.chgat.call_args_list, [
mock.call(0, 1, 38, 10 | contact_ui.curses.A_REVERSE),
mock.call(0, 1, 38, 10),
])
else:
self.assertEqual(ui_state.message_line_ranges[123], [])
pad.chgat.assert_not_called()
def test_build_reply_prefix_includes_sender_and_five_character_excerpt(self) -> None:
reply = contact_ui.build_reply_prefix(
"[06:27:25] >> [6] B1G1: ",