From 548e19a7cdfbc9298b7fd094e10f55a680342d29 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Wed, 4 Dec 2019 10:42:44 -0300 Subject: [PATCH] appDisplay: Remove Frequent view The Frequent apps grid has a few problems: * On a fresh install there would be no history of app usage so the applications shown in the grid have no relevance it takes time to be useful instead of being useful from the start; * The grid has far too many items in it to be relevant; 24 apps is well beyond the average use case as most people don't frequently use that many, so it gets populated with several apps that are single use (hello xterm); * The position of items in the grid are always changing based on an unknown frequency metric (and not by user-intended input) which makes it a poor way to quickly launch apps as one would have to constantly learn the positions of the items in the grid; * Having two app grids is a bit superfluous and needlessly complicates the app launching navigation: you have to spend time checking the frequent grid and if it's not there you have to switch over to another grid and find the app you need in there it's not straightforward. Remove the Frequent tab and simplify the related code. Related: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1425 https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/880 --- .../gnome-shell-sass/widgets/_app-grid.scss | 49 +--- js/ui/appDisplay.js | 227 +----------------- 2 files changed, 6 insertions(+), 270 deletions(-) diff --git a/data/theme/gnome-shell-sass/widgets/_app-grid.scss b/data/theme/gnome-shell-sass/widgets/_app-grid.scss index 1d2e135b4..c2b8f7e84 100644 --- a/data/theme/gnome-shell-sass/widgets/_app-grid.scss +++ b/data/theme/gnome-shell-sass/widgets/_app-grid.scss @@ -14,8 +14,6 @@ $app_icon_padding: 24px; } } -//.app-display { spacing: 20px; } - /* App Icons */ $app_grid_fg_color: #fff; @@ -123,15 +121,11 @@ $app_grid_fg_color: #fff; } // Some hacks I don't even know -.all-apps, -.frequent-apps > StBoxLayout { +.all-apps { // horizontal padding to make sure scrollbars or dash don't overlap content padding: 0px 88px 10px 88px; } -// Label when no frequent apps -.no-frequent-applications-label { @extend %status_text; } - // shutdown and other actions in the grid .system-action-icon { background-color: rgba(0,0,0,0.8); @@ -139,44 +133,3 @@ $app_grid_fg_color: #fff; border-radius: 99px; icon-size: $app_icon_size * 0.5; } - -/* Frequent | All toggle */ - -// container -.app-view-controls { - padding-bottom: 32px; -} - -// buttons -.app-view-control { - padding: 4px 32px; - margin: 0 4px; - - &, &:hover, &:checked { - @include button(undecorated); - color: darken($osd_fg_color, 25%); - } - - &:hover { - color: $osd_fg_color; - box-shadow: inset 0 -2px darken($osd_fg_color, 25%); - } - - &:active { - box-shadow: inset 0 -2px $osd_fg_color; - } - - &:checked { - color: $osd_fg_color; - box-shadow: inset 0 -2px $selected_bg_color; - } - - &:first-child { - border-right-width: 0; - border-radius: 0; - } - - &:last-child { - border-radius: 0; - } -} diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index 311430997..fb72b296c 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -29,8 +29,6 @@ var INACTIVE_GRID_OPACITY = 77; var INACTIVE_GRID_OPACITY_ANIMATION_TIME = 240; var FOLDER_SUBICON_FRACTION = .4; -var MIN_FREQUENT_APPS_COUNT = 3; - var VIEWS_SWITCH_TIME = 400; var VIEWS_SWITCH_ANIMATION_DELAY = 100; @@ -954,119 +952,6 @@ var AllView = GObject.registerClass({ } }); -var FrequentView = GObject.registerClass( -class FrequentView extends BaseAppView { - _init() { - super._init({ - style_class: 'frequent-apps', - layout_manager: new Clutter.BinLayout(), - x_expand: true, - y_expand: true, - }, { fillParent: true }); - - this._noFrequentAppsLabel = new St.Label({ text: _("Frequently used applications will appear here"), - style_class: 'no-frequent-applications-label', - x_align: Clutter.ActorAlign.CENTER, - x_expand: true, - y_align: Clutter.ActorAlign.CENTER, - y_expand: true }); - - this._grid.y_expand = true; - - this.add_actor(this._grid); - this.add_actor(this._noFrequentAppsLabel); - this._noFrequentAppsLabel.hide(); - - this._usage = Shell.AppUsage.get_default(); - } - - vfunc_map() { - this._redisplay(); - super.vfunc_map(); - } - - hasUsefulData() { - return this._usage.get_most_used().length >= MIN_FREQUENT_APPS_COUNT; - } - - _compareItems() { - // The FrequentView does not need to be sorted alphabetically - return 0; - } - - _loadApps() { - let apps = []; - let mostUsed = this._usage.get_most_used(); - let hasUsefulData = this.hasUsefulData(); - this._noFrequentAppsLabel.visible = !hasUsefulData; - if (!hasUsefulData) - return []; - - // Allow dragging of the icon only if the Dash would accept a drop to - // change favorite-apps. There are no other possible drop targets from - // the app picker, so there's no other need for a drag to start, - // at least on single-monitor setups. - // This also disables drag-to-launch on multi-monitor setups, - // but we hope that is not used much. - let favoritesWritable = global.settings.is_writable('favorite-apps'); - - for (let i = 0; i < mostUsed.length; i++) { - if (!this._parentalControlsManager.shouldShowApp(mostUsed[i].get_app_info())) - continue; - let appIcon = this._items.get(mostUsed[i].get_id()); - if (!appIcon) { - appIcon = new AppIcon(mostUsed[i], { - isDraggable: favoritesWritable, - }); - } - apps.push(appIcon); - } - - return apps; - } - - // Called before allocation to calculate dynamic spacing - adaptToSize(width, height) { - let box = new Clutter.ActorBox(); - box.x1 = box.y1 = 0; - box.x2 = width; - box.y2 = height; - box = this.get_theme_node().get_content_box(box); - box = this._grid.get_theme_node().get_content_box(box); - let availWidth = box.x2 - box.x1; - let availHeight = box.y2 - box.y1; - this._grid.adaptToSize(availWidth, availHeight); - } -}); - -var Views = { - FREQUENT: 0, - ALL: 1, -}; - -var ControlsBoxLayout = GObject.registerClass( -class ControlsBoxLayout extends Clutter.BoxLayout { - /* - * Override the BoxLayout behavior to use the maximum preferred width of all - * buttons for each child - */ - vfunc_get_preferred_width(container, forHeight) { - let maxMinWidth = 0; - let maxNaturalWidth = 0; - for (let child = container.get_first_child(); - child; - child = child.get_next_sibling()) { - let [minWidth, natWidth] = child.get_preferred_width(forHeight); - maxMinWidth = Math.max(maxMinWidth, minWidth); - maxNaturalWidth = Math.max(maxNaturalWidth, natWidth); - } - let childrenCount = container.get_n_children(); - let totalSpacing = this.spacing * (childrenCount - 1); - return [maxMinWidth * childrenCount + totalSpacing, - maxNaturalWidth * childrenCount + totalSpacing]; - } -}); - var ViewStackLayout = GObject.registerClass({ Signals: { 'allocated-size-changed': { param_types: [GObject.TYPE_INT, GObject.TYPE_INT] } }, @@ -1091,70 +976,14 @@ class AppDisplay extends St.BoxLayout { y_expand: true, }); - this._privacySettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.privacy' }); - this._privacySettings.connect('changed::remember-app-usage', - this._updateFrequentVisibility.bind(this)); - - this._views = []; - - let view, button; - view = new FrequentView(); - button = new St.Button({ label: _("Frequent"), - style_class: 'app-view-control button', - can_focus: true, - x_expand: true }); - this._views[Views.FREQUENT] = { view, 'control': button }; - - view = new AllView(); - button = new St.Button({ label: _("All"), - style_class: 'app-view-control button', - can_focus: true, - x_expand: true }); - this._views[Views.ALL] = { view, 'control': button }; - + this._view = new AllView(); this._viewStackLayout = new ViewStackLayout(); this._viewStack = new St.Widget({ x_expand: true, y_expand: true, layout_manager: this._viewStackLayout }); this._viewStackLayout.connect('allocated-size-changed', this._onAllocatedSizeChanged.bind(this)); this.add_actor(this._viewStack); - let layout = new ControlsBoxLayout({ homogeneous: true }); - this._controls = new St.Widget({ - style_class: 'app-view-controls', - layout_manager: layout, - x_align: Clutter.ActorAlign.CENTER, - }); - this._controls.connect('notify::mapped', () => { - // controls are faded either with their parent or - // explicitly in animate(); we can't know how they'll be - // shown next, so make sure to restore their opacity - // when they are hidden - if (this._controls.mapped) - return; - this._controls.remove_all_transitions(); - this._controls.opacity = 255; - }); - - layout.hookup_style(this._controls); - this.add_actor(new St.Bin({ child: this._controls })); - - for (let i = 0; i < this._views.length; i++) { - this._viewStack.add_actor(this._views[i].view); - this._controls.add_actor(this._views[i].control); - - let viewIndex = i; - this._views[i].control.connect('clicked', () => { - this._showView(viewIndex); - global.settings.set_uint('app-picker-view', viewIndex); - }); - } - let initialView = Math.min(global.settings.get_uint('app-picker-view'), - this._views.length - 1); - let frequentUseful = this._views[Views.FREQUENT].view.hasUsefulData(); - if (initialView == Views.FREQUENT && !frequentUseful) - initialView = Views.ALL; - this._showView(initialView); - this._updateFrequentVisibility(); + this._viewStack.add_actor(this._view); this._switcherooNotifyId = global.connect('notify::switcheroo-control', () => this._updateDiscreteGpuAvailable()); @@ -1172,56 +1001,11 @@ class AppDisplay extends St.BoxLayout { } animate(animationDirection, onComplete) { - let currentView = this._views.filter(v => v.control.has_style_pseudo_class('checked')).pop().view; - - // Animate controls opacity using iconGrid animation time, since - // it will be the time the AllView or FrequentView takes to show - // it entirely. - let finalOpacity; - if (animationDirection == IconGrid.AnimationDirection.IN) { - this._controls.opacity = 0; - finalOpacity = 255; - } else { - finalOpacity = 0; - } - - this._controls.ease({ - opacity: finalOpacity, - duration: IconGrid.ANIMATION_TIME_IN, - mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD, - }); - - currentView.animate(animationDirection, onComplete); - } - - _showView(activeIndex) { - for (let i = 0; i < this._views.length; i++) { - if (i == activeIndex) - this._views[i].control.add_style_pseudo_class('checked'); - else - this._views[i].control.remove_style_pseudo_class('checked'); - - let animationDirection = i == activeIndex - ? IconGrid.AnimationDirection.IN - : IconGrid.AnimationDirection.OUT; - this._views[i].view.animateSwitch(animationDirection); - } - } - - _updateFrequentVisibility() { - let enabled = this._privacySettings.get_boolean('remember-app-usage'); - this._views[Views.FREQUENT].control.visible = enabled; - - let visibleViews = this._views.filter(v => v.control.visible); - this._controls.visible = visibleViews.length > 1; - - if (!enabled && this._views[Views.FREQUENT].view.visible) - this._showView(Views.ALL); + this._view.animate(animationDirection, onComplete); } selectApp(id) { - this._showView(Views.ALL); - this._views[Views.ALL].view.selectApp(id); + this._view.selectApp(id); } _onAllocatedSizeChanged(actor, width, height) { @@ -1232,8 +1016,7 @@ class AppDisplay extends St.BoxLayout { box = this._viewStack.get_theme_node().get_content_box(box); let availWidth = box.x2 - box.x1; let availHeight = box.y2 - box.y1; - for (let i = 0; i < this._views.length; i++) - this._views[i].view.adaptToSize(availWidth, availHeight); + this._view.adaptToSize(availWidth, availHeight); } });