topic_list: Rewrite typeahead using an item type.

This makes it a lot easier to control the matching and display
separately.
This commit is contained in:
Tim Abbott
2025-07-15 16:32:30 -07:00
parent 421f5e9e0c
commit 24113b5dd5

View File

@@ -26,17 +26,28 @@ import type {TopicInfo} from "./topic_list_data.ts";
import * as typeahead_helper from "./typeahead_helper.ts"; import * as typeahead_helper from "./typeahead_helper.ts";
import * as vdom from "./vdom.ts"; import * as vdom from "./vdom.ts";
/* type TopicFilterPill = {
Track all active widgets with a Map by stream_id. label: string;
syntax: string;
};
(We have at max one for now, but we may const filter_options: TopicFilterPill[] = [
eventually allow multiple streams to be {
expanded.) label: $t({defaultMessage: "Unresolved topics"}),
*/ syntax: "-is:resolved",
},
{
label: $t({defaultMessage: "Resolved topics"}),
syntax: "is:resolved",
},
];
/* Track all active widgets with a Map by stream_id. We have at max
one for now, but we may eventually allow multiple streams to be
expanded. */
const active_widgets = new Map<number, LeftSidebarTopicListWidget>(); const active_widgets = new Map<number, LeftSidebarTopicListWidget>();
export let search_pill_widget: SearchPillWidget | null = null; export let search_pill_widget: SearchPillWidget | null = null;
export let topic_state_typeahead: Typeahead<string> | undefined; export let topic_state_typeahead: Typeahead<TopicFilterPill> | undefined;
// We know whether we're zoomed or not. // We know whether we're zoomed or not.
let zoomed = false; let zoomed = false;
@@ -500,12 +511,6 @@ function set_search_bar_text(text: string): void {
$input.trigger("input"); $input.trigger("input");
} }
const filter_options = new Map<string, string>([
[$t({defaultMessage: "Unresolved topics"}), "-is:resolved"],
[$t({defaultMessage: "Resolved topics"}), "is:resolved"],
[$t({defaultMessage: "All topics"}), ""],
]);
export function setup_topic_search_typeahead(): void { export function setup_topic_search_typeahead(): void {
const $input = $("#topic_filter_query"); const $input = $("#topic_filter_query");
const $pill_container = $("#left-sidebar-filter-topic-input"); const $pill_container = $("#left-sidebar-filter-topic-input");
@@ -522,7 +527,6 @@ export function setup_topic_search_typeahead(): void {
}; };
const options = { const options = {
items: filter_options.size,
source() { source() {
const stream_id = active_stream_id(); const stream_id = active_stream_id();
assert(stream_id !== undefined); assert(stream_id !== undefined);
@@ -534,27 +538,27 @@ export function setup_topic_search_typeahead(): void {
if ($pills.length > 0) { if ($pills.length > 0) {
return []; return [];
} }
return [...filter_options.keys()]; return [...filter_options];
}, },
item_html(item: string) { item_html(item: TopicFilterPill) {
return typeahead_helper.render_topic_state(item); return typeahead_helper.render_topic_state(item.label);
}, },
matcher(item: string, query: string) { matcher(item: TopicFilterPill, query: string) {
return item.toLowerCase().startsWith(query.toLowerCase()); return item.syntax.toLowerCase().startsWith(query.toLowerCase());
}, },
sorter(items: string[]) { sorter(items: TopicFilterPill[]) {
return items; return items;
}, },
updater(item: string) { updater(item: TopicFilterPill) {
const value = filter_options.get(item)!;
assert(search_pill_widget !== null); assert(search_pill_widget !== null);
search_pill_widget.clear(true); search_pill_widget.clear(true);
search_pill_widget.appendValue(value); search_pill_widget.appendValue(item.syntax);
set_search_bar_text(""); set_search_bar_text("");
$input.trigger("focus"); $input.trigger("focus");
return get_left_sidebar_topic_search_term(); return get_left_sidebar_topic_search_term();
}, },
// Prevents key events from propagating to other handlers or triggering default browser actions. // Prevents key events from propagating to other handlers or
// triggering default browser actions.
stopAdvance: true, stopAdvance: true,
// Use dropup, to match compose typeahead. // Use dropup, to match compose typeahead.
dropup: true, dropup: true,