mirror of
https://github.com/zulip/zulip.git
synced 2025-11-08 16:01:58 +00:00
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:
@@ -330,7 +330,7 @@ function elem($obj) {
|
|||||||
return {to_$: () => $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 $label1 = $.create("label1 stub");
|
||||||
const $label2 = $.create("label2 stub");
|
const $label2 = $.create("label2 stub");
|
||||||
|
|
||||||
@@ -376,6 +376,14 @@ test_ui("zoom_in_and_zoom_out", () => {
|
|||||||
};
|
};
|
||||||
stream_list.set_event_handlers();
|
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});
|
stream_list.zoom_in_topics({stream_id: 42});
|
||||||
|
|
||||||
assert.ok(!$label1.visible());
|
assert.ok(!$label1.visible());
|
||||||
@@ -384,6 +392,7 @@ test_ui("zoom_in_and_zoom_out", () => {
|
|||||||
assert.ok($stream_li1.visible());
|
assert.ok($stream_li1.visible());
|
||||||
assert.ok(!$stream_li2.visible());
|
assert.ok(!$stream_li2.visible());
|
||||||
assert.ok($("#streams_list").hasClass("zoom-in"));
|
assert.ok($("#streams_list").hasClass("zoom-in"));
|
||||||
|
assert.ok(filter_topics_appended);
|
||||||
|
|
||||||
$("#stream_filters li.narrow-filter").show = () => {
|
$("#stream_filters li.narrow-filter").show = () => {
|
||||||
$stream_li1.show();
|
$stream_li1.show();
|
||||||
@@ -391,6 +400,9 @@ test_ui("zoom_in_and_zoom_out", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$stream_li1.length = 1;
|
$stream_li1.length = 1;
|
||||||
|
$(".filter-topics").remove = () => {
|
||||||
|
filter_topics_appended = false;
|
||||||
|
};
|
||||||
stream_list.zoom_out_topics({$stream_li: $stream_li1});
|
stream_list.zoom_out_topics({$stream_li: $stream_li1});
|
||||||
|
|
||||||
assert.ok($label1.visible());
|
assert.ok($label1.visible());
|
||||||
@@ -399,6 +411,7 @@ test_ui("zoom_in_and_zoom_out", () => {
|
|||||||
assert.ok($stream_li1.visible());
|
assert.ok($stream_li1.visible());
|
||||||
assert.ok($stream_li2.visible());
|
assert.ok($stream_li2.visible());
|
||||||
assert.ok($("#streams_list").hasClass("zoom-out"));
|
assert.ok($("#streams_list").hasClass("zoom-out"));
|
||||||
|
assert.ok(!filter_topics_appended);
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("narrowing", ({mock_template}) => {
|
test_ui("narrowing", ({mock_template}) => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
|
||||||
|
import render_filter_topics from "../templates/filter_topics.hbs";
|
||||||
import render_stream_privacy from "../templates/stream_privacy.hbs";
|
import render_stream_privacy from "../templates/stream_privacy.hbs";
|
||||||
import render_stream_sidebar_row from "../templates/stream_sidebar_row.hbs";
|
import render_stream_sidebar_row from "../templates/stream_sidebar_row.hbs";
|
||||||
import render_stream_subheader from "../templates/streams_subheader.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) {
|
if (stream_id_for_elt($elt) === stream_id) {
|
||||||
$elt.show();
|
$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 {
|
} else {
|
||||||
$elt.hide();
|
$elt.hide();
|
||||||
}
|
}
|
||||||
@@ -289,6 +294,8 @@ export function zoom_out_topics() {
|
|||||||
|
|
||||||
$("#streams_list").expectOne().removeClass("zoom-in").addClass("zoom-out");
|
$("#streams_list").expectOne().removeClass("zoom-in").addClass("zoom-out");
|
||||||
$("#stream_filters li.narrow-filter").show();
|
$("#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) {
|
export function set_in_home_view(stream_id, in_home) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
import _ from "lodash";
|
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 from "../templates/more_topics.hbs";
|
||||||
import render_more_topics_spinner from "../templates/more_topics_spinner.hbs";
|
import render_more_topics_spinner from "../templates/more_topics_spinner.hbs";
|
||||||
import render_topic_list_item from "../templates/topic_list_item.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 {
|
export class TopicListWidget {
|
||||||
prior_dom = undefined;
|
prior_dom = undefined;
|
||||||
|
|
||||||
constructor($parent_elem, my_stream_id) {
|
constructor($parent_elem, my_stream_id) {
|
||||||
this.$parent_elem = $parent_elem;
|
this.$parent_elem = $parent_elem;
|
||||||
this.my_stream_id = my_stream_id;
|
this.my_stream_id = my_stream_id;
|
||||||
this.topic_search_text = "";
|
|
||||||
this.topic_search_focused_before_build = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
build_list(spinner) {
|
build_list(spinner) {
|
||||||
@@ -158,10 +144,6 @@ export class TopicListWidget {
|
|||||||
nodes.push(spinner_li());
|
nodes.push(spinner_li());
|
||||||
} else if (!is_showing_all_possible_topics) {
|
} else if (!is_showing_all_possible_topics) {
|
||||||
nodes.push(more_li(more_topics_unreads, more_topics_have_unread_mention_messages));
|
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({
|
const dom = vdom.ul({
|
||||||
@@ -180,50 +162,7 @@ export class TopicListWidget {
|
|||||||
return this.my_stream_id;
|
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() {
|
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.$parent_elem.find(".topic-list").remove();
|
||||||
this.prior_dom = undefined;
|
this.prior_dom = undefined;
|
||||||
}
|
}
|
||||||
@@ -234,7 +173,6 @@ export class TopicListWidget {
|
|||||||
const replace_content = (html) => {
|
const replace_content = (html) => {
|
||||||
this.remove();
|
this.remove();
|
||||||
this.$parent_elem.append(html);
|
this.$parent_elem.append(html);
|
||||||
this.update_topic_search_input();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const find = () => this.$parent_elem.find(".topic-list");
|
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);
|
vdom.update(replace_content, find, new_dom, this.prior_dom);
|
||||||
|
|
||||||
this.prior_dom = new_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();
|
e.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("body").on("input", "#filter-topic-input", () => {
|
||||||
|
active_widgets.get(active_stream_id()).build();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,6 +101,16 @@ li.show-more-topics {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
font-weight: normal;
|
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 {
|
li {
|
||||||
a {
|
a {
|
||||||
padding: 1px 0;
|
padding: 1px 0;
|
||||||
@@ -123,16 +133,6 @@ li.show-more-topics {
|
|||||||
z-index: 2;
|
z-index: 2;
|
||||||
background-color: hsl(0, 0%, 100%);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
<li class="topic-list-item filter-topics">
|
<div class="input-append topic_search_section filter-topics">
|
||||||
<div class="input-append topic_search_section">
|
|
||||||
<input class="topic-list-filter home-page-input" id="filter-topic-input" type="text" autocomplete="off" placeholder="{{t '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">
|
<button type="button" class="btn clear_search_button" id="clear_search_topic_button">
|
||||||
<i class="fa fa-remove" aria-hidden="true"></i>
|
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user