topic_list: Move topic filter out of topics list ul.

Instead of topic filter box being a part of the list when keeps
updating, we move it out and fix its position.

This should reduce rendering time of topics list and provide
a smoother experience to users when waiting for topics list to
load.
This commit is contained in:
Aman Agrawal
2022-11-02 16:38:38 +00:00
committed by Tim Abbott
parent d717b38704
commit ef067eafad
5 changed files with 47 additions and 81 deletions

View File

@@ -330,7 +330,7 @@ function elem($obj) {
return {to_$: () => $obj};
}
test_ui("zoom_in_and_zoom_out", () => {
test_ui("zoom_in_and_zoom_out", ({mock_template}) => {
const $label1 = $.create("label1 stub");
const $label2 = $.create("label2 stub");
@@ -376,6 +376,14 @@ test_ui("zoom_in_and_zoom_out", () => {
};
stream_list.set_event_handlers();
mock_template("filter_topics", false, () => "filter-topics-stub");
let filter_topics_appended = false;
$stream_li1.children = () => ({
append: (html) => {
assert.equal(html, "filter-topics-stub");
filter_topics_appended = true;
},
});
stream_list.zoom_in_topics({stream_id: 42});
assert.ok(!$label1.visible());
@@ -384,6 +392,7 @@ test_ui("zoom_in_and_zoom_out", () => {
assert.ok($stream_li1.visible());
assert.ok(!$stream_li2.visible());
assert.ok($("#streams_list").hasClass("zoom-in"));
assert.ok(filter_topics_appended);
$("#stream_filters li.narrow-filter").show = () => {
$stream_li1.show();
@@ -391,6 +400,9 @@ test_ui("zoom_in_and_zoom_out", () => {
};
$stream_li1.length = 1;
$(".filter-topics").remove = () => {
filter_topics_appended = false;
};
stream_list.zoom_out_topics({$stream_li: $stream_li1});
assert.ok($label1.visible());
@@ -399,6 +411,7 @@ test_ui("zoom_in_and_zoom_out", () => {
assert.ok($stream_li1.visible());
assert.ok($stream_li2.visible());
assert.ok($("#streams_list").hasClass("zoom-out"));
assert.ok(!filter_topics_appended);
});
test_ui("narrowing", ({mock_template}) => {

View File

@@ -1,6 +1,7 @@
import $ from "jquery";
import _ from "lodash";
import render_filter_topics from "../templates/filter_topics.hbs";
import render_stream_privacy from "../templates/stream_privacy.hbs";
import render_stream_sidebar_row from "../templates/stream_sidebar_row.hbs";
import render_stream_subheader from "../templates/streams_subheader.hbs";
@@ -265,6 +266,10 @@ export function zoom_in_topics(options) {
if (stream_id_for_elt($elt) === stream_id) {
$elt.show();
// Add search box for topics list.
$elt.children("div.bottom_left_row").append(render_filter_topics());
$("#filter-topic-input").trigger("focus");
$("#clear_search_topic_button").hide();
} else {
$elt.hide();
}
@@ -289,6 +294,8 @@ export function zoom_out_topics() {
$("#streams_list").expectOne().removeClass("zoom-in").addClass("zoom-out");
$("#stream_filters li.narrow-filter").show();
// Remove search box for topics list from DOM.
$(".filter-topics").remove();
}
export function set_in_home_view(stream_id, in_home) {

View File

@@ -1,7 +1,6 @@
import $ from "jquery";
import _ from "lodash";
import render_filter_topics from "../templates/filter_topics.hbs";
import render_more_topics from "../templates/more_topics.hbs";
import render_more_topics_spinner from "../templates/more_topics_spinner.hbs";
import render_topic_list_item from "../templates/topic_list_item.hbs";
@@ -117,25 +116,12 @@ export function spinner_li() {
};
}
function filter_topics_li() {
const eq = (other) => other.filter_topics;
return {
key: "filter",
filter_topics: true,
render: render_filter_topics,
eq,
};
}
export class TopicListWidget {
prior_dom = undefined;
constructor($parent_elem, my_stream_id) {
this.$parent_elem = $parent_elem;
this.my_stream_id = my_stream_id;
this.topic_search_text = "";
this.topic_search_focused_before_build = true;
}
build_list(spinner) {
@@ -158,10 +144,6 @@ export class TopicListWidget {
nodes.push(spinner_li());
} else if (!is_showing_all_possible_topics) {
nodes.push(more_li(more_topics_unreads, more_topics_have_unread_mention_messages));
} else if (zoomed) {
// In the zoomed topic view, we need to add the input
// for filtering through list of topics.
nodes.unshift(filter_topics_li());
}
const dom = vdom.ul({
@@ -180,50 +162,7 @@ export class TopicListWidget {
return this.my_stream_id;
}
update_topic_search_text(text) {
this.topic_search_text = text;
}
update_topic_search_input() {
const $input = this.$parent_elem.find("#filter-topic-input");
if ($input.length) {
// Restore topic search text saved in remove()
// after the element was rerendered.
$input.val(this.topic_search_text);
if (this.topic_search_focused_before_build) {
// Don't focus topic search if it wasn't focused before.
// This avoids unwanted change of focus.
$input.trigger("focus");
}
// set up display of clear(x) button.
if (this.topic_search_text.length) {
$("#clear_search_topic_button").show();
} else {
$("#clear_search_topic_button").hide();
}
// set up event handlers.
const rebuild_list = () => this.build();
$input.on("input", rebuild_list);
}
}
remove() {
// If text was present in the topic search filter, we store
// the input value lazily before removing old elements. This
// is a workaround for the quirk that the filter input is part
// of the region that we rerender.
const $input = this.$parent_elem.find("#filter-topic-input");
if ($input.length) {
this.update_topic_search_text($input.val());
// Only set focus on search input if it was focused before the update.
this.topic_search_focused_before_build =
document.activeElement.id === "filter-topic-input";
} else {
// Clear the topic search input when zooming out.
this.update_topic_search_text("");
}
this.$parent_elem.find(".topic-list").remove();
this.prior_dom = undefined;
}
@@ -234,7 +173,6 @@ export class TopicListWidget {
const replace_content = (html) => {
this.remove();
this.$parent_elem.append(html);
this.update_topic_search_input();
};
const find = () => this.$parent_elem.find(".topic-list");
@@ -242,6 +180,12 @@ export class TopicListWidget {
vdom.update(replace_content, find, new_dom, this.prior_dom);
this.prior_dom = new_dom;
if ($("#filter-topic-input").val() !== "") {
$("#clear_search_topic_button").show();
} else {
$("#clear_search_topic_button").hide();
}
}
}
@@ -374,4 +318,8 @@ export function initialize() {
e.preventDefault();
});
$("body").on("input", "#filter-topic-input", () => {
active_widgets.get(active_stream_id()).build();
});
}

View File

@@ -101,6 +101,16 @@ li.show-more-topics {
padding: 0;
font-weight: normal;
.input-append.topic_search_section {
padding: 2px 0 2px calc($topic_indent - $topic_resolve_width);
margin-bottom: 3px;
margin-left: 3px;
input {
width: calc(100% - 50px);
}
}
li {
a {
padding: 1px 0;
@@ -123,16 +133,6 @@ li.show-more-topics {
z-index: 2;
background-color: hsl(0, 0%, 100%);
}
.input-append.topic_search_section {
margin-bottom: 3px;
margin-left: 3px;
input {
padding-right: 20px;
width: calc(100% - 50px);
}
}
}
}
}

View File

@@ -1,8 +1,6 @@
<li class="topic-list-item filter-topics">
<div class="input-append topic_search_section">
<div class="input-append topic_search_section filter-topics">
<input class="topic-list-filter home-page-input" id="filter-topic-input" type="text" autocomplete="off" placeholder="{{t 'Filter topics'}}" />
<button type="button" class="btn clear_search_button" id="clear_search_topic_button">
<i class="fa fa-remove" aria-hidden="true"></i>
</button>
</div>
</li>
</div>