recent_topics: Fix annoying flicker on rerendering.

We were apparently not using the ListWidget API for replacing the
content of a widget without removing the whole thing from the DOM and
replacing it.

Unless ListWidget has unexpected bugs, this should have the exact same
result as the previous logic, with much a nicer user experience.
This commit is contained in:
Tim Abbott
2021-05-12 08:49:58 -07:00
committed by Tim Abbott
parent 4dae2c53fb
commit b0f8bbfbd4
2 changed files with 132 additions and 6 deletions

View File

@@ -38,6 +38,8 @@ const topic10 = "topic-10";
mock_cjs("jquery", $);
let expected_data_to_replace_in_list_widget;
const ListWidget = mock_esm("../../static/js/list_widget", {
modifier: noop,
@@ -63,6 +65,13 @@ const ListWidget = mock_esm("../../static/js/list_widget", {
hard_redraw: noop,
render_item: (item) => ListWidget.modifier(item),
replace_list_data: (data) => {
if (expected_data_to_replace_in_list_widget === undefined) {
throw new Error("You must set expected_data_to_replace_in_list_widget");
}
assert.deepEqual(data, expected_data_to_replace_in_list_widget);
expected_data_to_replace_in_list_widget = undefined;
},
});
mock_esm("../../static/js/compose_closed_ui", {
@@ -397,6 +406,11 @@ test("test_filter_all", (override) => {
rt.set_filter("all");
rt.process_messages([messages[0]]);
expected_data_to_replace_in_list_widget = [
{last_msg_id: 10, participated: true},
{last_msg_id: 1, participated: true},
];
row_data = row_data.concat(generate_topic_data([[1, "topic-7", 1, true, true]]));
i = row_data.length;
// topic is muted (=== hidden)
@@ -463,6 +477,42 @@ test("test_filter_unread", (override) => {
}
return "<recent_topics row stub>";
});
expected_data_to_replace_in_list_widget = [
{
last_msg_id: 11,
participated: true,
},
{
last_msg_id: 10,
participated: true,
},
{
last_msg_id: 9,
participated: true,
},
{
last_msg_id: 7,
participated: true,
},
{
last_msg_id: 5,
participated: false,
},
{
last_msg_id: 4,
participated: false,
},
{
last_msg_id: 3,
participated: true,
},
{
last_msg_id: 1,
participated: true,
},
];
rt.process_messages([messages[0]]);
// Unselect "unread" filter by clicking twice.
@@ -536,6 +586,41 @@ test("test_filter_participated", (override) => {
}
return "<recent_topics row stub>";
});
expected_data_to_replace_in_list_widget = [
{
last_msg_id: 11,
participated: true,
},
{
last_msg_id: 10,
participated: true,
},
{
last_msg_id: 9,
participated: true,
},
{
last_msg_id: 7,
participated: true,
},
{
last_msg_id: 5,
participated: false,
},
{
last_msg_id: 4,
participated: false,
},
{
last_msg_id: 3,
participated: true,
},
{
last_msg_id: 1,
participated: true,
},
];
rt.process_messages([messages[4]]);
expected.filter_participated = false;
@@ -571,6 +656,41 @@ test("basic assertions", (override) => {
// update a message
generate_topic_data([[1, "topic-7", 1, false, true]]);
stub_out_filter_buttons();
expected_data_to_replace_in_list_widget = [
{
last_msg_id: 11,
participated: true,
},
{
last_msg_id: 10,
participated: true,
},
{
last_msg_id: 9,
participated: true,
},
{
last_msg_id: 7,
participated: true,
},
{
last_msg_id: 5,
participated: false,
},
{
last_msg_id: 4,
participated: false,
},
{
last_msg_id: 3,
participated: true,
},
{
last_msg_id: 1,
participated: true,
},
];
rt.process_messages([messages[9]]);
// Check for expected lengths.
// total 8 topics, 1 muted

View File

@@ -584,8 +584,19 @@ export function complete_rerender() {
if (!is_visible()) {
return;
}
// Prepare header
// Update header
load_filters();
show_selected_filters();
// Show topics list
const mapped_topic_values = Array.from(get().values()).map((value) => value);
if (topics_widget) {
topics_widget.replace_list_data(mapped_topic_values);
return;
}
const rendered_body = render_recent_topics_body({
filter_participated: filters.has("participated"),
filter_unread: filters.has("unread"),
@@ -593,13 +604,8 @@ export function complete_rerender() {
search_val: $("#recent_topics_search").val() || "",
});
$("#recent_topics_table").html(rendered_body);
show_selected_filters();
// Show topics list
const container = $("#recent_topics_table table tbody");
container.empty();
const mapped_topic_values = Array.from(get().values()).map((value) => value);
topics_widget = ListWidget.create(container, mapped_topic_values, {
name: "recent_topics_table",
parent_container: $("#recent_topics_table"),