mirror of
https://github.com/zulip/zulip.git
synced 2025-11-12 01:47:41 +00:00
pm_list: Add search to direct message section.
Fixes #22113. The search will only be visible when in the `more conversations` view. Once we click `back to channels` and close the `more conversations` view, the search will clear and the search box will disappear. We've chosen `pm_list_data.get_conversations` as the function to which we will pass our search term. We could have technically found the value of the filter element via JQuery in pm_list_data, but pm_list_data does not handle any JQuery and we should keep it that way. `pm_list_data.get_list_info` also accepts the search_string so that the info it returns in expanded view is accurate. We've also added some code to `click_handlers` to make sure that clicking the search input does not bring us into the DM narrow.
This commit is contained in:
committed by
Tim Abbott
parent
188dd87eec
commit
76e8ec114a
@@ -774,7 +774,13 @@ export function initialize() {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
if (!$(e.target).hasClass("direct-messages-list-filter")) {
|
||||||
|
// Avoiding having clicks on the filter input.
|
||||||
|
//
|
||||||
|
// TODO: Refactor to use more precise selectors for this
|
||||||
|
// click handler in general; this is a fragile pattern.
|
||||||
window.location.hash = "narrow/is/dm";
|
window.location.hash = "narrow/is/dm";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// disable the draggability for left-sidebar components
|
// disable the draggability for left-sidebar components
|
||||||
|
|||||||
@@ -39,8 +39,10 @@ export function close(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function _build_direct_messages_list(): vdom.Tag<PMNode> {
|
export function _build_direct_messages_list(): vdom.Tag<PMNode> {
|
||||||
const conversations = pm_list_data.get_conversations();
|
const $filter = $<HTMLInputElement>(".direct-messages-list-filter").expectOne();
|
||||||
const pm_list_info = pm_list_data.get_list_info(zoomed);
|
const search_term = $filter.val()!;
|
||||||
|
const conversations = pm_list_data.get_conversations(search_term);
|
||||||
|
const pm_list_info = pm_list_data.get_list_info(zoomed, search_term);
|
||||||
const conversations_to_be_shown = pm_list_info.conversations_to_be_shown;
|
const conversations_to_be_shown = pm_list_info.conversations_to_be_shown;
|
||||||
const more_conversations_unread_count = pm_list_info.more_conversations_unread_count;
|
const more_conversations_unread_count = pm_list_info.more_conversations_unread_count;
|
||||||
|
|
||||||
@@ -55,6 +57,12 @@ export function _build_direct_messages_list(): vdom.Tag<PMNode> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const dom_ast = pm_list_dom.pm_ul(pm_list_nodes);
|
const dom_ast = pm_list_dom.pm_ul(pm_list_nodes);
|
||||||
|
|
||||||
|
if (search_term === "") {
|
||||||
|
$("#clear-direct-messages-search-button").hide();
|
||||||
|
} else {
|
||||||
|
$("#clear-direct-messages-search-button").show();
|
||||||
|
}
|
||||||
return dom_ast;
|
return dom_ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,16 +205,31 @@ function zoom_in(): void {
|
|||||||
$(".direct-messages-container").removeClass("zoom-out").addClass("zoom-in");
|
$(".direct-messages-container").removeClass("zoom-out").addClass("zoom-in");
|
||||||
$("#streams_list").hide();
|
$("#streams_list").hide();
|
||||||
$(".left-sidebar .right-sidebar-items").hide();
|
$(".left-sidebar .right-sidebar-items").hide();
|
||||||
|
|
||||||
|
const $filter = $(".direct-messages-list-filter").expectOne();
|
||||||
|
$filter.trigger("focus");
|
||||||
}
|
}
|
||||||
|
|
||||||
function zoom_out(): void {
|
function zoom_out(): void {
|
||||||
zoomed = false;
|
zoomed = false;
|
||||||
update_private_messages();
|
clear_search(true); // force rerender if the search is empty.
|
||||||
$(".direct-messages-container").removeClass("zoom-in").addClass("zoom-out");
|
$(".direct-messages-container").removeClass("zoom-in").addClass("zoom-out");
|
||||||
$("#streams_list").show();
|
$("#streams_list").show();
|
||||||
$(".left-sidebar .right-sidebar-items").show();
|
$(".left-sidebar .right-sidebar-items").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clear_search(force_rerender = false): void {
|
||||||
|
const $filter = $(".direct-messages-list-filter").expectOne();
|
||||||
|
if ($filter.val() !== "") {
|
||||||
|
$filter.val("");
|
||||||
|
update_private_messages();
|
||||||
|
} else if (force_rerender) {
|
||||||
|
update_private_messages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const throttled_update_private_message = _.throttle(update_private_messages, 50);
|
||||||
|
|
||||||
export function initialize(): void {
|
export function initialize(): void {
|
||||||
$(".direct-messages-container").on("click", "#show-more-direct-messages", (e) => {
|
$(".direct-messages-container").on("click", "#show-more-direct-messages", (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -221,4 +244,18 @@ export function initialize(): void {
|
|||||||
|
|
||||||
zoom_out();
|
zoom_out();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(".direct-messages-container").on("input", ".direct-messages-list-filter", (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
throttled_update_private_message();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".direct-messages-container").on("click", "#clear-direct-messages-search-button", (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
clear_search();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ type DisplayObject = {
|
|||||||
is_bot: boolean;
|
is_bot: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function get_conversations(): DisplayObject[] {
|
export function get_conversations(search_string = ""): DisplayObject[] {
|
||||||
const conversations = pm_conversations.recent.get();
|
const conversations = pm_conversations.recent.get();
|
||||||
const display_objects = [];
|
const display_objects = [];
|
||||||
|
|
||||||
@@ -66,6 +66,16 @@ export function get_conversations(): DisplayObject[] {
|
|||||||
|
|
||||||
for (const conversation of conversations) {
|
for (const conversation of conversations) {
|
||||||
const user_ids_string = conversation.user_ids_string;
|
const user_ids_string = conversation.user_ids_string;
|
||||||
|
|
||||||
|
const users = people.get_users_from_ids(
|
||||||
|
people.user_ids_string_to_ids_array(user_ids_string),
|
||||||
|
);
|
||||||
|
if (!people.dm_matches_search_string(users, search_string)) {
|
||||||
|
// Skip adding the conversation to the display_objects array if it does
|
||||||
|
// not match the search_term.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const reply_to = people.user_ids_string_to_emails_string(user_ids_string);
|
const reply_to = people.user_ids_string_to_emails_string(user_ids_string);
|
||||||
assert(reply_to !== undefined);
|
assert(reply_to !== undefined);
|
||||||
const recipients_string = people.get_recipients(user_ids_string);
|
const recipients_string = people.get_recipients(user_ids_string);
|
||||||
@@ -110,11 +120,14 @@ export function get_conversations(): DisplayObject[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Designed to closely match topic_list_data.get_list_info().
|
// Designed to closely match topic_list_data.get_list_info().
|
||||||
export function get_list_info(zoomed: boolean): {
|
export function get_list_info(
|
||||||
|
zoomed: boolean,
|
||||||
|
search_term = "",
|
||||||
|
): {
|
||||||
conversations_to_be_shown: DisplayObject[];
|
conversations_to_be_shown: DisplayObject[];
|
||||||
more_conversations_unread_count: number;
|
more_conversations_unread_count: number;
|
||||||
} {
|
} {
|
||||||
const conversations = get_conversations();
|
const conversations = get_conversations(search_term);
|
||||||
|
|
||||||
if (zoomed || conversations.length <= max_conversations_to_show) {
|
if (zoomed || conversations.length <= max_conversations_to_show) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1130,6 +1130,13 @@ li.topic-list-item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Since direct-messages-sticky-header also has the `input-append`
|
||||||
|
class accompanying it. The display property of that class will
|
||||||
|
overwrite display: none if we don't have a more specific CSS
|
||||||
|
rule. It will also overwrite `display: none` even if `.zoom-out`
|
||||||
|
properties are declared after the `.input-append` properties since
|
||||||
|
the latter is more specific. */
|
||||||
|
#direct-messages-sticky-header.zoom-out,
|
||||||
.zoom-out {
|
.zoom-out {
|
||||||
#topics_header {
|
#topics_header {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -1225,8 +1232,45 @@ li.topic-list-item {
|
|||||||
vertical centering. */
|
vertical centering. */
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.stream-list-filter {
|
&.hide_unread_counts {
|
||||||
|
.unread_count,
|
||||||
|
.unread_count.hide,
|
||||||
|
.masked_unread_count {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When an empty unread count is hidden,
|
||||||
|
hide the masked unread count, too. */
|
||||||
|
.unread_count.hide + .masked_unread_count {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.masked_unread_count {
|
||||||
|
display: block;
|
||||||
|
/* Hold space enough so single-digit
|
||||||
|
unreads don't shift on hover. */
|
||||||
|
margin: 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.unread_count {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide,
|
||||||
|
.masked_unread_count {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream_search_section,
|
||||||
|
.direct-messages-search-section {
|
||||||
|
.stream-list-filter,
|
||||||
|
.direct-messages-list-filter {
|
||||||
/* Use the border-box model so flex
|
/* Use the border-box model so flex
|
||||||
can do its thing despite whatever
|
can do its thing despite whatever
|
||||||
padding and border we specify. */
|
padding and border we specify. */
|
||||||
@@ -1272,39 +1316,6 @@ li.topic-list-item {
|
|||||||
to make a generous clickable area. */
|
to make a generous clickable area. */
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&.hide_unread_counts {
|
|
||||||
.unread_count,
|
|
||||||
.unread_count.hide,
|
|
||||||
.masked_unread_count {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When an empty unread count is hidden,
|
|
||||||
hide the masked unread count, too. */
|
|
||||||
.unread_count.hide + .masked_unread_count {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.masked_unread_count {
|
|
||||||
display: block;
|
|
||||||
/* Hold space enough so single-digit
|
|
||||||
unreads don't shift on hover. */
|
|
||||||
margin: 0 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.unread_count {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hide,
|
|
||||||
.masked_unread_count {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare an adjusted grid for the logged-out state,
|
/* Prepare an adjusted grid for the logged-out state,
|
||||||
@@ -1415,6 +1426,13 @@ li.topic-list-item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.direct-messages-search-section {
|
||||||
|
display: flex;
|
||||||
|
grid-column: row-content / markers-and-controls;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.zoom-in-hide {
|
.zoom-in-hide {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,6 +155,12 @@
|
|||||||
<a class="zoom-out-hide" id="hide-more-direct-messages">
|
<a class="zoom-out-hide" id="hide-more-direct-messages">
|
||||||
<span class="hide-more-direct-messages-text"> {{t 'back to channels' }}</span>
|
<span class="hide-more-direct-messages-text"> {{t 'back to channels' }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
<div class="zoom-out-hide direct-messages-search-section">
|
||||||
|
<input class="direct-messages-list-filter filter_text_input" type="text" autocomplete="off" placeholder="{{t 'Filter direct messages' }}" />
|
||||||
|
<button type="button" class="btn clear_search_button" id="clear-direct-messages-search-button">
|
||||||
|
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{~!-- squash whitespace --~}}
|
{{~!-- squash whitespace --~}}
|
||||||
<div id="left_sidebar_scroll_container" class="scrolling_list" data-simplebar data-simplebar-tab-index="-1">
|
<div id="left_sidebar_scroll_container" class="scrolling_list" data-simplebar data-simplebar-tab-index="-1">
|
||||||
|
|||||||
@@ -163,6 +163,19 @@ test("get_conversations", ({override}) => {
|
|||||||
set_pm_with_filter("iago@zulip.com");
|
set_pm_with_filter("iago@zulip.com");
|
||||||
pm_data = pm_list_data.get_conversations();
|
pm_data = pm_list_data.get_conversations();
|
||||||
assert.deepEqual(pm_data, expected_data);
|
assert.deepEqual(pm_data, expected_data);
|
||||||
|
|
||||||
|
pm_data = pm_list_data.get_conversations("Ia");
|
||||||
|
assert.deepEqual(
|
||||||
|
pm_data,
|
||||||
|
expected_data.filter((item) => item.recipients === "Iago"),
|
||||||
|
);
|
||||||
|
|
||||||
|
// filter should work with email
|
||||||
|
pm_data = pm_list_data.get_conversations("me@zulip");
|
||||||
|
assert.deepEqual(
|
||||||
|
pm_data,
|
||||||
|
expected_data.filter((item) => item.recipients === "Me Myself"),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("get_conversations bot", ({override}) => {
|
test("get_conversations bot", ({override}) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user