| Index: components/ntp_snippets/reading_list/reading_list_suggestions_provider.cc
|
| diff --git a/components/ntp_snippets/reading_list/reading_list_suggestions_provider.cc b/components/ntp_snippets/reading_list/reading_list_suggestions_provider.cc
|
| index f8eeb57b9ff11b7ecf4bb0fd670b587442daad84..5dbcbe660098db6be08f880ee7203d9bfc9c9e14 100644
|
| --- a/components/ntp_snippets/reading_list/reading_list_suggestions_provider.cc
|
| +++ b/components/ntp_snippets/reading_list/reading_list_suggestions_provider.cc
|
| @@ -4,18 +4,30 @@
|
|
|
| #include "components/ntp_snippets/reading_list/reading_list_suggestions_provider.h"
|
|
|
| +#include <algorithm>
|
| #include <vector>
|
|
|
| #include "base/bind.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| #include "components/ntp_snippets/category.h"
|
| #include "components/reading_list/core/reading_list_entry.h"
|
| #include "components/reading_list/core/reading_list_model.h"
|
| #include "components/strings/grit/components_strings.h"
|
| +#include "components/url_formatter/url_formatter.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
|
|
| namespace ntp_snippets {
|
|
|
| +namespace {
|
| +// Max number of entries to return.
|
| +const int kMaxEntries = 3;
|
| +
|
| +bool CompareEntries(const ReadingListEntry* lhs, const ReadingListEntry* rhs) {
|
| + return lhs->UpdateTime() > rhs->UpdateTime();
|
| +}
|
| +}
|
| +
|
| ReadingListSuggestionsProvider::ReadingListSuggestionsProvider(
|
| ContentSuggestionsProvider::Observer* observer,
|
| ReadingListModel* reading_list_model)
|
| @@ -23,18 +35,17 @@ ReadingListSuggestionsProvider::ReadingListSuggestionsProvider(
|
| category_status_(CategoryStatus::AVAILABLE_LOADING),
|
| provided_category_(
|
| Category::FromKnownCategory(KnownCategories::READING_LIST)),
|
| - reading_list_model_(reading_list_model) {
|
| + reading_list_model_(reading_list_model),
|
| + scoped_observer_(this) {
|
| observer->OnCategoryStatusChanged(this, provided_category_, category_status_);
|
| - reading_list_model->AddObserver(this);
|
| - if (reading_list_model_->loaded()) {
|
| - FetchReadingListInternal();
|
| - }
|
| -}
|
|
|
| -ReadingListSuggestionsProvider::~ReadingListSuggestionsProvider() {
|
| - reading_list_model_->RemoveObserver(this);
|
| + // If the ReadingListModel is loaded, this will trigger a call to
|
| + // ReadingListModelLoaded. Keep it as last instruction.
|
| + scoped_observer_.Add(reading_list_model_);
|
| }
|
|
|
| +ReadingListSuggestionsProvider::~ReadingListSuggestionsProvider(){};
|
| +
|
| CategoryStatus ReadingListSuggestionsProvider::GetCategoryStatus(
|
| Category category) {
|
| DCHECK_EQ(category, provided_category_);
|
| @@ -107,8 +118,62 @@ void ReadingListSuggestionsProvider::ReadingListModelLoaded(
|
| FetchReadingListInternal();
|
| }
|
|
|
| +void ReadingListSuggestionsProvider::ReadingListModelBeingDeleted(
|
| + const ReadingListModel* model) {
|
| + DCHECK(model == reading_list_model_);
|
| + scoped_observer_.Remove(reading_list_model_);
|
| + reading_list_model_ = nullptr;
|
| +}
|
| +
|
| void ReadingListSuggestionsProvider::FetchReadingListInternal() {
|
| - // TODO(crbug.com/702241): Implement this method.
|
| + if (!reading_list_model_)
|
| + return;
|
| +
|
| + DCHECK(reading_list_model_->loaded());
|
| + std::vector<const ReadingListEntry*> entries;
|
| + for (const GURL& url : reading_list_model_->Keys()) {
|
| + const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
|
| + if (!entry->IsRead()) {
|
| + entries.emplace_back(entry);
|
| + }
|
| + }
|
| +
|
| + if (entries.size() > kMaxEntries) {
|
| + // Get the |kMaxEntries| most recent entries.
|
| + std::partial_sort(entries.begin(), entries.begin() + kMaxEntries,
|
| + entries.end(), CompareEntries);
|
| + entries.resize(kMaxEntries);
|
| + } else {
|
| + std::sort(entries.begin(), entries.end(), CompareEntries);
|
| + }
|
| +
|
| + std::vector<ContentSuggestion> suggestions;
|
| + for (const ReadingListEntry* entry : entries) {
|
| + ContentSuggestion suggestion(provided_category_, entry->URL().spec(),
|
| + entry->URL());
|
| +
|
| + if (!entry->Title().empty()) {
|
| + suggestion.set_title(base::UTF8ToUTF16(entry->Title()));
|
| + } else {
|
| + suggestion.set_title(url_formatter::FormatUrl(entry->URL()));
|
| + }
|
| + suggestion.set_publisher_name(
|
| + url_formatter::FormatUrl(entry->URL().GetOrigin()));
|
| + suggestions.emplace_back(std::move(suggestion));
|
| + }
|
| +
|
| + NotifyStatusChanged(CategoryStatus::AVAILABLE);
|
| + observer()->OnNewSuggestions(this, provided_category_,
|
| + std::move(suggestions));
|
| +}
|
| +
|
| +void ReadingListSuggestionsProvider::NotifyStatusChanged(
|
| + CategoryStatus new_status) {
|
| + if (category_status_ == new_status) {
|
| + return;
|
| + }
|
| + category_status_ = new_status;
|
| + observer()->OnCategoryStatusChanged(this, provided_category_, new_status);
|
| }
|
|
|
| } // namespace ntp_snippets
|
|
|