diff --git a/browser/components/urlbar/UrlbarInput.jsm b/browser/components/urlbar/UrlbarInput.jsm index bd7c7e7c6339..60f46ea61261 100644 --- a/browser/components/urlbar/UrlbarInput.jsm +++ b/browser/components/urlbar/UrlbarInput.jsm @@ -487,7 +487,7 @@ class UrlbarInput { }; let selIndex = this.view.selectedIndex; - if (!result.payload.isKeywordOffer) { + if (!result.payload.keywordOffer) { this.view.close(); } @@ -544,7 +544,7 @@ class UrlbarInput { return; } case UrlbarUtils.RESULT_TYPE.SEARCH: { - if (result.payload.isKeywordOffer) { + if (result.payload.keywordOffer) { // The user confirmed a token alias, so just move the caret // to the end of it. Because there's a trailing space in the value, // the user can directly start typing a query string at that point. diff --git a/browser/components/urlbar/UrlbarProviderUnifiedComplete.jsm b/browser/components/urlbar/UrlbarProviderUnifiedComplete.jsm index f2d02307ee9c..5870f02ce436 100644 --- a/browser/components/urlbar/UrlbarProviderUnifiedComplete.jsm +++ b/browser/components/urlbar/UrlbarProviderUnifiedComplete.jsm @@ -208,19 +208,21 @@ function convertResultToMatches(context, result, urls) { } urls.add(url); let style = result.getStyleAt(i); + let isHeuristic = i == 0 && style.includes("heuristic"); let match = makeUrlbarResult(context.tokens, { url, icon: result.getImageAt(i), style, comment: result.getCommentAt(i), firstToken: context.tokens[0], + isHeuristic, }); // Should not happen, but better safe than sorry. if (!match) { continue; } // Manage autofill and preselected properties for the first match. - if (i == 0 && style.includes("heuristic")) { + if (isHeuristic) { if (style.includes("autofill") && result.defaultIndex == 0) { let autofillValue = result.getValueAt(i); if ( @@ -256,7 +258,17 @@ function makeUrlbarResult(tokens, info) { let action = PlacesUtils.parseActionUrl(info.url); if (action) { switch (action.type) { - case "searchengine": + case "searchengine": { + let keywordOffer = UrlbarUtils.KEYWORD_OFFER.NONE; + if ( + action.params.alias && + !action.params.searchQuery.trim() && + action.params.alias.startsWith("@") + ) { + keywordOffer = info.isHeuristic + ? UrlbarUtils.KEYWORD_OFFER.HIDE + : UrlbarUtils.KEYWORD_OFFER.SHOW; + } return new UrlbarResult( UrlbarUtils.RESULT_TYPE.SEARCH, UrlbarUtils.RESULT_SOURCE.SEARCH, @@ -272,13 +284,10 @@ function makeUrlbarResult(tokens, info) { UrlbarUtils.HIGHLIGHT.TYPED, ], icon: [info.icon], - isKeywordOffer: [ - action.params.alias && - !action.params.searchQuery.trim() && - action.params.alias.startsWith("@"), - ], + keywordOffer, }) ); + } case "keyword": { let title = info.comment; if (!title) { diff --git a/browser/components/urlbar/UrlbarResult.jsm b/browser/components/urlbar/UrlbarResult.jsm index afdc04d5c83c..579fdf7f7454 100644 --- a/browser/components/urlbar/UrlbarResult.jsm +++ b/browser/components/urlbar/UrlbarResult.jsm @@ -116,10 +116,11 @@ class UrlbarResult { ? [this.payload.title, this.payloadHighlights.title] : [this.payload.url || "", this.payloadHighlights.url || []]; case UrlbarUtils.RESULT_TYPE.SEARCH: - if (this.payload.isKeywordOffer) { - return this.heuristic - ? ["", []] - : [this.payload.keyword, this.payloadHighlights.keyword]; + switch (this.payload.keywordOffer) { + case UrlbarUtils.KEYWORD_OFFER.SHOW: + return [this.payload.keyword, this.payloadHighlights.keyword]; + case UrlbarUtils.KEYWORD_OFFER.HIDE: + return ["", []]; } return this.payload.suggestion ? [this.payload.suggestion, this.payloadHighlights.suggestion] diff --git a/browser/components/urlbar/UrlbarUtils.jsm b/browser/components/urlbar/UrlbarUtils.jsm index 84328bee26ca..13700b6616c3 100644 --- a/browser/components/urlbar/UrlbarUtils.jsm +++ b/browser/components/urlbar/UrlbarUtils.jsm @@ -135,6 +135,17 @@ var UrlbarUtils = { SUGGESTED: 2, }, + // Search results with keywords and empty queries are called "keyword offers". + // When the user selects a keyword offer, the keyword followed by a space is + // put in the input as a hint that the user can search using the keyword. + // Depending on the use case, keyword-offer results can show or not show the + // keyword itself. + KEYWORD_OFFER: { + NONE: 0, + SHOW: 1, + HIDE: 2, + }, + // UnifiedComplete's autocomplete results store their titles and tags together // in their comments. This separator is used to separate them. When we // rewrite UnifiedComplete for quantumbar, we should stop using this old hack diff --git a/browser/components/urlbar/UrlbarView.jsm b/browser/components/urlbar/UrlbarView.jsm index afa9483e7b81..87b32038c185 100644 --- a/browser/components/urlbar/UrlbarView.jsm +++ b/browser/components/urlbar/UrlbarView.jsm @@ -586,7 +586,7 @@ class UrlbarView { if ( result.type == UrlbarUtils.RESULT_TYPE.SEARCH && - !result.payload.isKeywordOffer + !result.payload.keywordOffer ) { item.setAttribute("type", "search"); } else if (result.type == UrlbarUtils.RESULT_TYPE.REMOTE_TAB) { diff --git a/browser/components/urlbar/docs/overview.rst b/browser/components/urlbar/docs/overview.rst index 5b156e53d1e2..d24bc2344c26 100644 --- a/browser/components/urlbar/docs/overview.rst +++ b/browser/components/urlbar/docs/overview.rst @@ -374,7 +374,7 @@ The following RESULT_TYPEs are supported: // Payload: { icon, url, userContextId } TAB_SWITCH: 1, - // Payload: { icon, suggestion, keyword, query, isKeywordOffer } + // Payload: { icon, suggestion, keyword, query, keywordOffer } SEARCH: 2, // Payload: { icon, url, title, tags } URL: 3, diff --git a/browser/themes/shared/urlbar-autocomplete.inc.css b/browser/themes/shared/urlbar-autocomplete.inc.css index 2f290f9b05e1..829601d9f258 100644 --- a/browser/themes/shared/urlbar-autocomplete.inc.css +++ b/browser/themes/shared/urlbar-autocomplete.inc.css @@ -149,12 +149,15 @@ font-weight: 600; } -.urlbarView-secondary { +.urlbarView-title:not(:empty) ~ .urlbarView-secondary { color: var(--urlbar-popup-action-color); } .urlbarView-url { overflow: hidden; +} + +.urlbarView-title:not(:empty) ~ .urlbarView-url { color: var(--urlbar-popup-url-color); }