chromium/ash/picker/model/picker_model.cc

// Copyright 2023 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/picker/model/picker_model.h"

#include "ash/constants/ash_pref_names.h"
#include "ash/picker/model/picker_mode_type.h"
#include "ash/public/cpp/picker/picker_category.h"
#include "base/check_deref.h"
#include "chromeos/components/editor_menu/public/cpp/editor_helpers.h"
#include "components/prefs/pref_service.h"
#include "ui/base/ime/ash/ime_keyboard.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/range/range.h"

namespace ash {
namespace {

std::u16string GetSelectedText(ui::TextInputClient* client) {
  gfx::Range selection_range;
  std::u16string result;
  if (client && client->GetEditableSelectionRange(&selection_range) &&
      selection_range.IsValid() && !selection_range.is_empty() &&
      client->GetTextFromRange(selection_range, &result)) {
    return result;
  }
  return u"";
}

gfx::Range GetSelectionRange(ui::TextInputClient* client) {
  gfx::Range selection_range;
  return client && client->GetEditableSelectionRange(&selection_range)
             ? selection_range
             : gfx::Range();
}

ui::TextInputType GetTextInputType(ui::TextInputClient* client) {
  return client ? client->GetTextInputType()
                : ui::TextInputType::TEXT_INPUT_TYPE_NONE;
}

bool GetIsGifsEnabled(PrefService* prefs) {
  // prefs can be null in some tests.
  if (prefs == nullptr) {
    return false;
  }

  if (const PrefService::Preference* pref =
          prefs->FindPreference(prefs::kEmojiPickerGifSupportEnabled)) {
    return pref->GetValue()->GetBool();
  }
  return false;
}

}  // namespace

PickerModel::PickerModel(PrefService* prefs,
                         ui::TextInputClient* focused_client,
                         input_method::ImeKeyboard* ime_keyboard,
                         EditorStatus editor_status)
    : has_focus_(focused_client != nullptr &&
                 focused_client->GetTextInputType() !=
                     ui::TextInputType::TEXT_INPUT_TYPE_NONE),
      selected_text_(GetSelectedText(focused_client)),
      should_do_learning_(focused_client == nullptr ||
                          focused_client->ShouldDoLearning()),
      selection_range_(GetSelectionRange(focused_client)),
      is_caps_lock_enabled_(CHECK_DEREF(ime_keyboard).IsCapsLockEnabled()),
      editor_status_(editor_status),
      text_input_type_(GetTextInputType(focused_client)),
      is_gifs_enabled_(GetIsGifsEnabled(prefs)) {}

std::vector<PickerCategory> PickerModel::GetAvailableCategories() const {
  switch (GetMode()) {
    case PickerModeType::kUnfocused:
      return std::vector<PickerCategory>{
          PickerCategory::kLinks,
          PickerCategory::kDriveFiles,
          PickerCategory::kLocalFiles,
      };
    case PickerModeType::kHasSelection: {
      std::vector<PickerCategory> categories;
      if (editor_status_ == EditorStatus::kEnabled) {
        categories.push_back(PickerCategory::kEditorRewrite);
      }
      return categories;
    }
    case PickerModeType::kNoSelection: {
      std::vector<PickerCategory> categories;
      if (editor_status_ == EditorStatus::kEnabled) {
        categories.push_back(PickerCategory::kEditorWrite);
      }
      categories.push_back(PickerCategory::kLinks);
      if (text_input_type_ != ui::TextInputType::TEXT_INPUT_TYPE_URL) {
        categories.push_back(is_gifs_enabled_ ? PickerCategory::kEmojisGifs
                                              : PickerCategory::kEmojis);
      }
      categories.insert(categories.end(), {
                                              PickerCategory::kClipboard,
                                              PickerCategory::kDriveFiles,
                                              PickerCategory::kLocalFiles,
                                              PickerCategory::kDatesTimes,
                                              PickerCategory::kUnitsMaths,
                                          });

      return categories;
    }
    case PickerModeType::kPassword: {
      return {};
    }
  }
}

std::vector<PickerCategory> PickerModel::GetRecentResultsCategories() const {
  if (GetMode() == PickerModeType::kHasSelection) {
    return std::vector<PickerCategory>{};
  }

  return {
      PickerCategory::kDriveFiles,
      PickerCategory::kLocalFiles,
      PickerCategory::kLinks,
  };
}

std::u16string_view PickerModel::selected_text() const {
  return selected_text_;
}

bool PickerModel::should_do_learning() const {
  return should_do_learning_;
}

bool PickerModel::is_caps_lock_enabled() const {
  return is_caps_lock_enabled_;
}

PickerModeType PickerModel::GetMode() const {
  if (!has_focus_) {
    return PickerModeType::kUnfocused;
  }

  if (text_input_type_ == ui::TextInputType::TEXT_INPUT_TYPE_PASSWORD) {
    return PickerModeType::kPassword;
  }

  return chromeos::editor_helpers::NonWhitespaceAndSymbolsLength(
             selected_text_, gfx::Range(0, selected_text_.size())) == 0
             ? PickerModeType::kNoSelection
             : PickerModeType::kHasSelection;
}

bool PickerModel::IsGifsEnabled() const {
  return is_gifs_enabled_;
}

}  // namespace ash