diff --git a/app/assets/javascripts/discourse/app/controllers/keyboard-shortcuts-help.js b/app/assets/javascripts/discourse/app/controllers/keyboard-shortcuts-help.js
index 65eacc5cdfe..03864510566 100644
--- a/app/assets/javascripts/discourse/app/controllers/keyboard-shortcuts-help.js
+++ b/app/assets/javascripts/discourse/app/controllers/keyboard-shortcuts-help.js
@@ -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,
+ }),
},
});
},
diff --git a/app/assets/javascripts/discourse/app/templates/modal/keyboard-shortcuts-help.hbs b/app/assets/javascripts/discourse/app/templates/modal/keyboard-shortcuts-help.hbs
index 60edf99f9f9..9488750a378 100644
--- a/app/assets/javascripts/discourse/app/templates/modal/keyboard-shortcuts-help.hbs
+++ b/app/assets/javascripts/discourse/app/templates/modal/keyboard-shortcuts-help.hbs
@@ -100,6 +100,7 @@
- {{html-safe shortcuts.search_menu.prev_next}}
- {{html-safe shortcuts.search_menu.insert_url}}
+ - {{html-safe shortcuts.search_menu.full_page_search}}
diff --git a/app/assets/javascripts/discourse/app/widgets/search-menu.js b/app/assets/javascripts/discourse/app/widgets/search-menu.js
index ad03c11b4a6..e5366f5be63 100644
--- a/app/assets/javascripts/discourse/app/widgets/search-menu.js
+++ b/app/assets/javascripts/discourse/app/widgets/search-menu.js
@@ -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();
diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-test.js
index d3f39aeff8d..6be320421a7 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/search-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/search-test.js
@@ -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");
});
});
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 2a35962d3e0..bb9066166bf 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -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: