chromium/ash/app_list/model/app_icon_load_helper.cc

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

#include "ash/app_list/model/app_icon_load_helper.h"

#include <algorithm>
#include <utility>

#include "ash/app_list/model/folder_image.h"
#include "base/check.h"
#include "base/memory/raw_ptr.h"

namespace ash {

// AppIconLoadHelper::AppItemHelper
class AppIconLoadHelper::AppItemHelper : public AppListItemObserver {
 public:
  AppItemHelper(AppListItem* app_item, IconLoadCallback icon_load_callback);
  AppItemHelper(const AppItemHelper&) = delete;
  AppItemHelper& operator=(const AppItemHelper&) = delete;
  ~AppItemHelper() override;

  // AppListItemObserver:
  void ItemIconVersionChanged() override;
  void ItemBeingDestroyed() override;

  const AppListItem* app_item() const { return app_item_; }

 private:
  raw_ptr<AppListItem> app_item_ = nullptr;
  IconLoadCallback icon_load_callback_;
  base::ScopedObservation<AppListItem, AppListItemObserver>
      app_item_observeration_{this};
};

AppIconLoadHelper::AppItemHelper::AppItemHelper(
    AppListItem* app_item,
    IconLoadCallback icon_load_callback)
    : app_item_(app_item), icon_load_callback_(std::move(icon_load_callback)) {
  DCHECK(!icon_load_callback_.is_null());

  app_item_observeration_.Observe(app_item_.get());

  if (app_item_->GetDefaultIcon().isNull())
    icon_load_callback_.Run(app_item_->id());
}

AppIconLoadHelper::AppItemHelper::~AppItemHelper() = default;

void AppIconLoadHelper::AppItemHelper::ItemIconVersionChanged() {
  icon_load_callback_.Run(app_item_->id());
}

void AppIconLoadHelper::AppItemHelper::ItemBeingDestroyed() {
  app_item_ = nullptr;
  app_item_observeration_.Reset();
}

// AppIconLoadHelper::AppItemListHelper
class AppIconLoadHelper::AppItemListHelper : public AppListItemListObserver {
 public:
  AppItemListHelper(AppListItemList* list, IconLoadCallback icon_load_callback);
  AppItemListHelper(const AppItemListHelper&) = delete;
  AppItemListHelper& operator=(const AppItemListHelper&) = delete;
  ~AppItemListHelper() override;

  // AppListItemListObserver:
  void OnListItemAdded(size_t index, AppListItem* item) override;
  void OnListItemRemoved(size_t index, AppListItem* item) override;
  void OnListItemMoved(size_t from_index,
                       size_t to_index,
                       AppListItem* item) override;

 private:
  using AppItemHelper = AppIconLoadHelper::AppItemHelper;

  void UpdateHelper();

  const raw_ptr<AppListItemList> list_;
  IconLoadCallback icon_load_callback_;
  base::ScopedObservation<AppListItemList, AppListItemListObserver>
      list_observeration_{this};
  std::vector<std::unique_ptr<AppItemHelper>> icon_helpers_;
};

AppIconLoadHelper::AppItemListHelper::AppItemListHelper(
    AppListItemList* list,
    IconLoadCallback icon_load_callback)
    : list_(list), icon_load_callback_(std::move(icon_load_callback)) {
  DCHECK(!icon_load_callback_.is_null());

  list_observeration_.Observe(list_.get());

  UpdateHelper();
}

AppIconLoadHelper::AppItemListHelper::~AppItemListHelper() = default;

void AppIconLoadHelper::AppItemListHelper::OnListItemAdded(size_t index,
                                                           AppListItem* item) {
  if (index < FolderImage::kNumFolderTopItems)
    UpdateHelper();
}

void AppIconLoadHelper::AppItemListHelper::OnListItemRemoved(
    size_t index,
    AppListItem* item) {
  if (index < FolderImage::kNumFolderTopItems)
    UpdateHelper();
}

void AppIconLoadHelper::AppItemListHelper::OnListItemMoved(size_t from_index,
                                                           size_t to_index,
                                                           AppListItem* item) {
  if (from_index < FolderImage::kNumFolderTopItems ||
      to_index < FolderImage::kNumFolderTopItems) {
    UpdateHelper();
  }
}

void AppIconLoadHelper::AppItemListHelper::UpdateHelper() {
  icon_helpers_.clear();

  const size_t count =
      std::min(FolderImage::kNumFolderTopItems, list_->item_count());
  for (size_t i = 0; i < count; ++i) {
    AppListItem* app_item = list_->item_at(i);
    icon_helpers_.emplace_back(
        std::make_unique<AppItemHelper>(app_item, icon_load_callback_));
  }
}

// AppIconLoadHelper
AppIconLoadHelper::AppIconLoadHelper(AppListItem* app_item,
                                     IconLoadCallback icon_load_callback)
    : item_helper_(
          std::make_unique<AppItemHelper>(app_item,
                                          std::move(icon_load_callback))) {}

AppIconLoadHelper::AppIconLoadHelper(AppListItemList* list,
                                     IconLoadCallback icon_load_callback)
    : list_helper_(
          std::make_unique<AppItemListHelper>(list,
                                              std::move(icon_load_callback))) {}

AppIconLoadHelper::~AppIconLoadHelper() = default;

}  // namespace ash