1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195

ash / wm / overview / birch / birch_bar_controller.h [blame]

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_WM_OVERVIEW_BIRCH_BIRCH_BAR_CONTROLLER_H_
#define ASH_WM_OVERVIEW_BIRCH_BIRCH_BAR_CONTROLLER_H_

#include <vector>

#include "ash/ash_export.h"
#include "ash/birch/birch_coral_provider.h"
#include "ash/birch/birch_model.h"
#include "ash/wm/overview/birch/birch_bar_constants.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "components/prefs/pref_change_registrar.h"
#include "ui/base/mojom/menu_source_type.mojom-forward.h"
#include "ui/gfx/geometry/point.h"
#include "ui/menus/simple_menu_model.h"

class PrefRegistrySimple;

namespace ash {

inline constexpr char kUserFeedbackPrompt[] =
    "## Your Feedback Matters!\n"
    "We're always looking for ways to improve the smart grouping. "
    "Please tell us what you think:\n\n\n"
    "----------\n"
    "Auto-generated logs:\n";

inline constexpr char kMarkdownBackticks[] = "```";

class BirchBarMenuModelAdapter;
class BirchBarView;
class BirchChipButton;
class BirchItem;

// The controller used to manage the birch bar in every `OverviewGrid`. It will
// fetch data from `BirchModel` and distribute the data to birch bars.
class ASH_EXPORT BirchBarController : public BirchModel::Observer,
                                      public ui::SimpleMenuModel::Delegate,
                                      public BirchCoralProvider::Observer {
 public:
  explicit BirchBarController(bool from_pine_service);
  BirchBarController(const BirchBarController&) = delete;
  BirchBarController& operator=(const BirchBarController&) = delete;
  ~BirchBarController() override;

  // Gets the instance of the controller. It can be nullptr when the Overview
  // session is shutting down.
  static BirchBarController* Get();

  static void RegisterProfilePrefs(PrefRegistrySimple* registry);

  std::vector<raw_ptr<BirchBarView>>& bar_views() { return bar_views_; }

  bool is_informed_restore() const { return is_informed_restore_; }

  // Register a bar view.
  void RegisterBar(BirchBarView* bar_view);

  // Called if the given `bar_view` is being destroyed.
  void OnBarDestroying(BirchBarView* bar_view);

  // Show a context menu for the chip which is right clicked by the user.
  void ShowChipContextMenu(BirchChipButton* chip,
                           BirchSuggestionType chip_type,
                           const gfx::Point& point,
                           ui::mojom::MenuSourceType source_type);

  // Called if a suggestion is hidden by user from context menu.
  void OnItemHiddenByUser(BirchItem* item);

  // Called if the user shows/hides the suggestions from context menu.
  void SetShowBirchSuggestions(bool show);

  // Gets if the user allows the suggestions to show.
  bool GetShowBirchSuggestions() const;

  // Called if the user shows/hides the given type of suggestions.
  void SetShowSuggestionType(BirchSuggestionType type, bool show);

  // Gets if the user allows to show the given type of suggestions.
  bool GetShowSuggestionType(BirchSuggestionType type) const;

  // Gets if the suggestion data loading is in progress.
  bool IsDataLoading() const;

  // Toggles temperature units for weather chip between F and C.
  void ToggleTemperatureUnits();

  // Launches feedback diaglog for Coral items.
  void ProvideFeedbackForCoral();

  // Executes the commands from bar and chip context menus. `from_chip` will be
  // true if the command is from a chip context menu.
  // Please note that most of the bar menu commands should be executed by the
  // switch button and checkboxes, see `BirchBarMenuModelAdapter` for details.
  // However, due to the way how `MenuController` processes gesture events, the
  // submenu may close on touch such that switch button and checkbox callbacks
  // are not triggered. To solve the issue, we make `SimpleMenuModel::Delegate`
  // to execute the commands for switch button and checkboxes on touch event.
  // This is not a normal usage. For more details, please see the bug comment in
  // http://b/360072119.
  void ExecuteMenuCommand(int command_id, bool from_chip);

  // ui::SimpleMenuModel::Delegate:
  void ExecuteCommand(int command_id, int event_flags) override;

  // BirchCoralProvider::Observer:
  void OnCoralGroupRemoved(const base::Token& group_id) override;
  void OnCoralEntityRemoved(const base::Token& group_id,
                            std::string_view identifier) override;
  void OnCoralGroupTitleUpdated(const base::Token& group_id,
                                const std::string& title) override;

  BirchBarMenuModelAdapter* chip_menu_model_adapter_for_testing() {
    return chip_menu_model_adapter_.get();
  }

 private:
  friend class BirchBarTestBase;

  // Fetches data from birch model if there is no fetching in progress.
  void MaybeFetchDataFromModel();

  // Called when birch items are fetched from model or the fetching process
  // timed out.
  void OnItemsFetchedFromModel();

  // initialize the given `bar_view` with the `items`.
  void InitBarWithItems(BirchBarView* bar_view,
                        const std::vector<std::unique_ptr<BirchItem>>& items);

  // Remove the chips corresponding to the given `item` from the bars and fill
  // in the chips if there are extra items to show. Note that the `item` is not
  // removed from `items_` list in this method.
  void RemoveItemChips(BirchItem* item);

  // Called when the context menu is closed.
  void OnChipContextMenuClosed();

  // BirchModel::Observer:
  void OnBirchClientSet() override;

  // Called when the show suggestions pref changes.
  void OnShowSuggestionsPrefChanged();

  // Called when the customize suggestion prefs change.
  void OnCustomizeSuggestionsPrefChanged();

  // Called when recevice a lost media item.
  void OnLostMediaItemReceived();

  // Called when the lost media is removed.
  void OnLostMediaItemRemoved();

  // Called when the lost media item is updated with the `updated_item`.
  void OnLostMediaItemUpdated(std::unique_ptr<BirchItem> updated_item);

  // Birch items fetched from model.
  std::vector<std::unique_ptr<BirchItem>> items_;

  std::unique_ptr<BirchBarMenuModelAdapter> chip_menu_model_adapter_;

  std::vector<raw_ptr<BirchBarView>> bar_views_;

  // Indicates if the data fetching is in progress.
  bool data_fetch_in_progress_ = false;

  // True if the overview session is an informed restore session.
  const bool is_informed_restore_;

  // Show/hide suggestions pref change registrar.
  PrefChangeRegistrar show_suggestions_pref_registrar_;

  // Customize suggestions pref change registrar.
  PrefChangeRegistrar customize_suggestions_pref_registrar_;

  // To avoid sending multiple data requests when reset suggestions, the
  // variable is used as an indicator to block the data request from
  // `OnCustomizeSuggestionsPrefChanged`.
  bool hold_data_request_on_suggestion_pref_change_ = false;

  base::ScopedObservation<BirchModel, BirchModel::Observer>
      birch_model_observer_{this};

  base::WeakPtrFactory<BirchBarController> weak_ptr_factory_{this};
};

}  // namespace ash

#endif  // ASH_WM_OVERVIEW_BIRCH_BIRCH_BAR_CONTROLLER_H_