Compare commits

...

13 Commits

Author SHA1 Message Date
raresvis
de814752d6 search.js: Vertically center the provider icon 2017-07-05 01:00:49 +03:00
raresvis
c36f006b88 update sass 2017-07-05 00:56:41 +03:00
raresvis
bf884ae9ea search.js: Apply the bold style in real time 2017-07-05 00:32:16 +03:00
raresvis
7bbff9d0c0 search.js: Propagate searchResultsView down the hierarchy 2017-07-05 00:32:09 +03:00
Florian Müllner
04ad2b24d8 util: Wrap g_regex_escape_string() 2017-07-04 22:34:18 +03:00
raresvis
4ffbec5b75 search.js: Increase maximum number of visible list search results 2017-07-04 22:34:18 +03:00
raresvis
d35f2d375b gnome-shell.css: Make search result description semitransparent 2017-07-04 22:34:18 +03:00
raresvis
235d4b244d gnome-shell.css: Use standard font size for the search-result-title class 2017-07-04 22:34:18 +03:00
raresvis
9a007058ae search.js: Replace the gradient separator with a simple line 2017-07-04 22:34:18 +03:00
raresvis
985e53a04e search.js: Tweak the sizes of search results icons
Just a small tweak of icon sizes. This patch could be easily
included in any of the two bigger patches.
2017-07-04 22:34:18 +03:00
raresvis
aed6d466cb search.js: Refactor providerIcon into providerInfo
In order to match the current mockups, the providerIcon
class needed to include both the name of the provider
and the label that informs the user about how many more
search results are available for that specific provider.
The latter replaces the plus sign icon that has been
used so far.

https://bugzilla.gnome.org/show_bug.cgi?id=749957
2017-07-04 22:34:14 +03:00
raresvis
c62e3614d5 search.js: Make the results take more horizontal space
In order to make gnome-shell search functionality fit on
smaller screens, like those of devices, search results
need to take advantage of more horizontal space so that
any extra space can be used efficiently.

In order to do so, change the layout of the ListSearchResult
class from a vertical one, to a horizontal one and also
decrease the padding of the list-search-result-content css
class.

https://bugzilla.gnome.org/show_bug.cgi?id=749957
2017-07-01 02:53:25 +03:00
raresvis
8dae0b5767 update sass 2017-07-01 02:24:57 +03:00
7 changed files with 165 additions and 63 deletions

View File

@ -1180,14 +1180,19 @@ StScrollBar {
.list-search-result-content {
spacing: 12px;
padding: 12px; }
padding: 2px; }
.list-search-result-title {
font-size: 1.5em;
color: #e2e2df; }
.list-search-result-provider {
color: #e2e2df;
margin-top: 0.24em; }
.list-search-result-description {
color: #cacac4; }
color: #cacac4;
margin-left: 30px; }
.search-provider-icon {
padding: 15px; }

@ -1 +1 @@
Subproject commit 2bef9b25e23632fe66e12c5d96a9c487f172a6a0
Subproject commit 664cd88ee6fce1c9699512c83e0b68e45052fc23

View File

@ -1171,23 +1171,30 @@ StScrollBar {
.list-search-results {
spacing: 3px; }
.list-search-provider-details {
spacing: 3px;
width: 150px;
margin-left: 30px; }
.search-section-separator {
-gradient-height: 1px;
-gradient-start: rgba(255, 255, 255, 0);
-gradient-end: rgba(255, 255, 255, 0.1);
-margin-horizontal: 1.5em;
height: 1px; }
height: 2px;
background-color: rgba(255, 255, 255, 0.2); }
.list-search-result-content {
spacing: 12px;
padding: 12px; }
padding: 2px; }
.list-search-result-title {
font-size: 1.5em;
color: #e2e2df; }
.list-search-result-provider {
color: #e2e2df;
margin-top: 0.24em;
}
.list-search-result-description {
color: #cacac4; }
color: rgba(202, 202, 196, 0.5);
margin-left: 30px; }
.search-provider-icon {
padding: 15px; }

View File

@ -1131,7 +1131,7 @@ const AppSearchProvider = new Lang.Class({
this.getInitialResultSet(terms, callback, cancellable);
},
createResultObject: function (resultMeta) {
createResultObject: function (resultMeta, searchResultsView) {
let app = this._appSys.lookup_app(resultMeta['id']);
return new AppIcon(app);
}

View File

@ -22,7 +22,7 @@ const Util = imports.misc.util;
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
const MAX_LIST_SEARCH_RESULTS_ROWS = 5;
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
const MaxWidthBin = new Lang.Class({
@ -48,9 +48,10 @@ const MaxWidthBin = new Lang.Class({
const SearchResult = new Lang.Class({
Name: 'SearchResult',
_init: function(provider, metaInfo) {
_init: function(provider, metaInfo, searchResultsView) {
this.provider = provider;
this.metaInfo = metaInfo;
this._searchResultsView = searchResultsView;
this.actor = new St.Button({ reactive: true,
can_focus: true,
@ -72,10 +73,10 @@ const ListSearchResult = new Lang.Class({
Name: 'ListSearchResult',
Extends: SearchResult,
ICON_SIZE: 64,
ICON_SIZE: 24,
_init: function(provider, metaInfo) {
this.parent(provider, metaInfo);
_init: function(provider, metaInfo, searchResultsView) {
this.parent(provider, metaInfo, searchResultsView);
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
@ -90,7 +91,7 @@ const ListSearchResult = new Lang.Class({
content.add(icon);
}
let details = new St.BoxLayout({ vertical: true });
let details = new St.BoxLayout({ vertical: false });
content.add(details, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
@ -101,17 +102,38 @@ const ListSearchResult = new Lang.Class({
details.add(title, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
y_align: St.Align.MIDDLE });
this.actor.label_actor = title;
this._descriptionLabel =
new St.Label({
style_class: 'list-search-result-description' });
if (this.metaInfo['description']) {
let description = new St.Label({ style_class: 'list-search-result-description' });
description.clutter_text.set_markup(this.metaInfo['description']);
details.add(description, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.END });
this._highlightTerms();
details.add(this._descriptionLabel, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
}
this._termsChangedSignal =
this._searchResultsView.connect(
'terms-changed',
Lang.bind(this, this._highlightTerms));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
},
_highlightTerms: function() {
if (!this.metaInfo['description'] || !this._descriptionLabel || !this._searchResultsView)
return;
this._descriptionLabel.clutter_text.set_markup(this._searchResultsView.highlightTerms(this.metaInfo['description']));
},
_onDestroy: function() {
this._searchResultsView.disconnect(this._termsChangedSignal);
}
});
@ -119,8 +141,8 @@ const GridSearchResult = new Lang.Class({
Name: 'GridSearchResult',
Extends: SearchResult,
_init: function(provider, metaInfo) {
this.parent(provider, metaInfo);
_init: function(provider, metaInfo, searchResultsView) {
this.parent(provider, metaInfo, searchResultsView);
this.actor.style_class = 'grid-search-result';
@ -135,8 +157,9 @@ const GridSearchResult = new Lang.Class({
const SearchResultsBase = new Lang.Class({
Name: 'SearchResultsBase',
_init: function(provider) {
_init: function(provider, searchResultsView) {
this.provider = provider;
this._searchResultsView = searchResultsView;
this._terms = [];
@ -147,8 +170,8 @@ const SearchResultsBase = new Lang.Class({
y_fill: true });
this.actor.add(this._resultDisplayBin, { expand: true });
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
this.actor.add(separator.actor);
let separator = new St.DrawingArea({ style_class: 'search-section-separator' });
this.actor.add(separator);
this._resultDisplays = {};
@ -164,7 +187,8 @@ const SearchResultsBase = new Lang.Class({
_createResultDisplay: function(meta) {
if (this.provider.createResultObject)
return this.provider.createResultObject(meta);
return this.provider.createResultObject(meta,
this._searchResultsView);
return null;
},
@ -188,7 +212,7 @@ const SearchResultsBase = new Lang.Class({
Main.overview.toggle();
},
_setMoreIconVisible: function(visible) {
_setMoreLabelVisible: function(visible, moreNumber) {
},
_ensureResultActors: function(results, callback) {
@ -231,7 +255,6 @@ const SearchResultsBase = new Lang.Class({
updateSearch: function(providerResults, terms, callback) {
this._terms = terms;
if (providerResults.length == 0) {
this._clearResultDisplay();
this.actor.hide();
@ -256,7 +279,8 @@ const SearchResultsBase = new Lang.Class({
results.forEach(Lang.bind(this, function(resultId) {
this._addItem(this._resultDisplays[resultId]);
}));
this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch);
this._setMoreLabelVisible(hasMoreResults && this.provider.canLaunchSearch,
providerResults.length - results.length);
this.actor.show();
callback();
}));
@ -268,20 +292,20 @@ const ListSearchResults = new Lang.Class({
Name: 'ListSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
_init: function(provider, searchResultsView) {
this.parent(provider, searchResultsView);
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerIcon = new ProviderIcon(provider);
this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerIcon.connect('clicked', Lang.bind(this,
this.providerInfo = new ProviderInfo(provider);
this.providerInfo.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerInfo.connect('clicked', Lang.bind(this,
function() {
this.providerIcon.animateLaunch();
this.providerInfo.animateLaunch();
provider.launchSearch(this._terms);
Main.overview.toggle();
}));
this._container.add(this.providerIcon, { x_fill: false,
this._container.add(this.providerInfo, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
@ -293,8 +317,8 @@ const ListSearchResults = new Lang.Class({
this._resultDisplayBin.set_child(this._container);
},
_setMoreIconVisible: function(visible) {
this.providerIcon.moreIcon.visible = visible;
_setMoreLabelVisible: function(visible, moreNumber) {
this.providerInfo.setMoreVisible(visible, moreNumber);
},
_getMaxDisplayedResults: function() {
@ -306,7 +330,8 @@ const ListSearchResults = new Lang.Class({
},
_createResultDisplay: function(meta) {
return this.parent(meta) || new ListSearchResult(this.provider, meta);
return this.parent(meta, this._searchResultsView) ||
new ListSearchResult(this.provider, meta, this._searchResultsView);
},
_addItem: function(display) {
@ -326,14 +351,14 @@ const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults',
Extends: SearchResultsBase,
_init: function(provider, parentContainer) {
this.parent(provider);
_init: function(provider, searchResultsView) {
this.parent(provider, searchResultsView);
// We need to use the parent container to know how much results we can show.
// None of the actors in this class can be used for that, since the main actor
// goes hidden when no results are displayed, and then it lost its allocation.
// Then on the next use of _getMaxDisplayedResults allocation is 0, en therefore
// it doesn't show any result although we have some.
this._parentContainer = parentContainer;
this._parentContainer = searchResultsView.actor;
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
@ -354,7 +379,8 @@ const GridSearchResults = new Lang.Class({
},
_createResultDisplay: function(meta) {
return this.parent(meta) || new GridSearchResult(this.provider, meta);
return this.parent(meta, this._searchResultsView) ||
new GridSearchResult(this.provider, meta, this._searchResultsView);
},
_addItem: function(display) {
@ -418,6 +444,8 @@ const SearchResults = new Lang.Class({
this._providers = [];
this._searchTermRegex = null;
this._searchSettings = new Gio.Settings({ schema_id: SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::enabled', Lang.bind(this, this._reloadRemoteProviders));
@ -537,6 +565,14 @@ const SearchResults = new Lang.Class({
if (this._searchTimeoutId == 0)
this._searchTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, Lang.bind(this, this._onSearchTimeout));
let escapedSearchTerms = this._terms.map(
(currentTerm, index, array) =>
{ return Shell.util_regex_escape(currentTerm) });
this._searchTermRegex =
new RegExp(`(${escapedSearchTerms.join('|')})`, 'gi');
this.emit('terms-changed');
},
_onPan: function(action) {
@ -556,9 +592,9 @@ const SearchResults = new Lang.Class({
let providerDisplay;
if (provider.appInfo)
providerDisplay = new ListSearchResults(provider);
providerDisplay = new ListSearchResults(provider, this);
else
providerDisplay = new GridSearchResults(provider, this.actor);
providerDisplay = new GridSearchResults(provider, this);
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
providerDisplay.actor.hide();
@ -675,14 +711,22 @@ const SearchResults = new Lang.Class({
} else {
result.actor.remove_style_pseudo_class('selected');
}
},
highlightTerms: function(description) {
if (!description)
return '';
return description.replace(this._searchTermRegex, '<b>$1</b>');
}
});
Signals.addSignalMethods(SearchResults.prototype);
const ProviderIcon = new Lang.Class({
Name: 'ProviderIcon',
const ProviderInfo = new Lang.Class({
Name: 'ProviderInfo',
Extends: St.Button,
PROVIDER_ICON_SIZE: 48,
PROVIDER_ICON_SIZE: 32,
_init: function(provider) {
this.provider = provider;
@ -692,22 +736,45 @@ const ProviderIcon = new Lang.Class({
accessible_name: provider.appInfo.get_name(),
track_hover: true });
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._content = new St.BoxLayout({ vertical: false });
this.set_child(this._content);
let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL);
this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more',
visible: false,
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true });
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
gicon: provider.appInfo.get_icon() });
this._content.add_actor(icon);
this._content.add_actor(this.moreIcon);
this._providerDetails = new St.BoxLayout({
style_class: 'list-search-provider-details',
vertical: true });
let providerNameLabel = new St.Label({
style_class: 'list-search-result-provider',
text: provider.appInfo.get_name() });
this._remainingResultsLabel = new St.Label({
style_class: 'list-search-result-title' });
this._providerDetails.add(providerNameLabel,
{ x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._providerDetails.add(this._remainingResultsLabel,
{ x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._content.add(icon, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
this._content.add(this._providerDetails, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
},
animateLaunch: function() {
@ -715,5 +782,11 @@ const ProviderIcon = new Lang.Class({
let app = appSys.lookup_app(this.provider.appInfo.get_id());
if (app.state == Shell.AppState.STOPPED)
IconGrid.zoomOutActor(this._content);
},
setMoreVisible: function(visible, resultsCount) {
this._remainingResultsLabel.visible = visible;
this._remainingResultsLabel.clutter_text.set_markup(
_("%d more").format(resultsCount));
}
});

View File

@ -240,6 +240,21 @@ shell_util_translate_time_string (const char *str)
return res;
}
/**
* shell_util_regex_escape:
* @str: a UTF-8 string to escape
*
* A wrapper around g_regex_escape_string() that takes its argument as
* \0-terminated string rather than a byte-array the confuses gjs.
*
* Returns: @str with all regex-special characters escaped
*/
char *
shell_util_regex_escape (const char *str)
{
return g_regex_escape_string (str, -1);
}
/**
* shell_write_string_to_stream:
* @stream: a #GOutputStream

View File

@ -24,6 +24,8 @@ char *shell_util_format_date (const char *format,
gint64 time_ms);
const char *shell_util_translate_time_string (const char *str);
char *shell_util_regex_escape (const char *str);
gboolean shell_write_string_to_stream (GOutputStream *stream,
const char *str,
GError **error);