UX: launch full page search on second `Enter` hit (#14978)

This commit is contained in:
Penar Musaraj 2021-11-17 00:35:17 -05:00 committed by GitHub
parent c61d47e6f4
commit 2ff7f105d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 4 deletions

View File

@ -232,6 +232,10 @@ export default Controller.extend(ModalFunctionality, {
insert_url: buildShortcut("search_menu.insert_url", {
keys1: ["a"],
}),
full_page_search: buildShortcut("search_menu.full_page_search", {
keys1: [translateModKey("Meta"), "Enter"],
keysDelimiter: PLUS,
}),
},
});
},

View File

@ -100,6 +100,7 @@
<ul>
<li>{{html-safe shortcuts.search_menu.prev_next}}</li>
<li>{{html-safe shortcuts.search_menu.insert_url}}</li>
<li>{{html-safe shortcuts.search_menu.full_page_search}}</li>
</ul>
</section>
</div>

View File

@ -16,6 +16,7 @@ import { cancel } from "@ember/runloop";
const CATEGORY_SLUG_REGEXP = /(\#[a-zA-Z0-9\-:]*)$/gi;
const USERNAME_REGEXP = /(\@[a-zA-Z0-9\-\_]*)$/gi;
const SUGGESTIONS_REGEXP = /(in:|status:|order:|:)([a-zA-Z]*)$/gi;
const SECOND_ENTER_MAX_DELAY = 15000;
export const MODIFIER_REGEXP = /.*(\#|\@|:).*$/gi;
export const DEFAULT_TYPE_FILTER = "exclude_topics";
@ -111,14 +112,14 @@ const SearchHelper = {
if (!term) {
searchData.noResults = false;
searchData.results = [];
searchData.results = {};
searchData.loading = false;
searchData.invalidTerm = false;
widget.scheduleRerender();
} else if (!isValidSearchTerm(term, widget.siteSettings)) {
searchData.noResults = true;
searchData.results = [];
searchData.results = {};
searchData.loading = false;
searchData.invalidTerm = true;
@ -191,6 +192,7 @@ export default createWidget("search-menu", {
defaultState(attrs) {
return {
inTopicContext: attrs.inTopicContext,
_lastEnterTimestamp: null,
_debouncer: null,
};
},
@ -418,13 +420,23 @@ export default createWidget("search-menu", {
const searchInput = document.querySelector("#search-term");
if (e.which === 13 && e.target === searchInput) {
const recentEnterHit =
this.state._lastEnterTimestamp &&
Date.now() - this.state._lastEnterTimestamp < SECOND_ENTER_MAX_DELAY;
// same combination as key-enter-escape mixin
if (e.ctrlKey || e.metaKey || (isiPad() && e.altKey)) {
if (
e.ctrlKey ||
e.metaKey ||
(isiPad() && e.altKey) ||
(searchData.typeFilter !== DEFAULT_TYPE_FILTER && recentEnterHit)
) {
this.fullSearch();
} else {
searchData.typeFilter = null;
this.triggerSearch();
}
this.state._lastEnterTimestamp = Date.now();
}
if (e.target === searchInput && e.which === 8 /* backspace */) {
@ -477,7 +489,6 @@ export default createWidget("search-menu", {
},
fullSearch() {
searchData.results = [];
searchData.loading = false;
SearchHelper.cancel();
const url = this.fullSearchUrl();

View File

@ -480,6 +480,31 @@ acceptance("Search - Authenticated", function (needs) {
`${window.location.origin}${firstLink}`,
"hitting A when focused on a search result copies link to composer"
);
await click("#search-button");
await triggerKeyEvent("#search-term", "keydown", keyEnter);
assert.ok(
exists(query(`${container} .search-result-topic`)),
"has topic results"
);
await triggerKeyEvent("#search-term", "keydown", keyEnter);
assert.ok(
exists(query(`.search-container`)),
"second Enter hit goes to full page search"
);
assert.ok(
!exists(query(`.search-menu`)),
"search dropdown is collapsed after second Enter hit"
);
// new search launched, Enter key should be reset
await click("#search-button");
assert.ok(exists(query(`${container} ul li`)), "has a list of items");
await triggerKeyEvent("#search-term", "keydown", keyEnter);
assert.ok(exists(query(`.search-menu`)), "search dropdown is visible");
});
});

View File

@ -3720,6 +3720,7 @@ en:
title: "Search Menu"
prev_next: "%{shortcut} Move selection up and down"
insert_url: "%{shortcut} Insert selection into open composer"
full_page_search: "%{shortcut} Launches full page search"
badges:
earned_n_times: