blob: da606291dd7bd9d6007918c45ad6f1aa06123dd7 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_FEED_CORE_V2_SURFACE_UPDATER_H_
#define COMPONENTS_FEED_CORE_V2_SURFACE_UPDATER_H_
#include <map>
#include <string>
#include <vector>
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "components/feed/core/proto/v2/ui.pb.h"
#include "components/feed/core/proto/v2/wire/reliability_logging_enums.pb.h"
#include "components/feed/core/v2/enums.h"
#include "components/feed/core/v2/launch_reliability_logger.h"
#include "components/feed/core/v2/stream_model.h"
#include "components/feed/core/v2/stream_surface_set.h"
#include "components/feed/core/v2/types.h"
#include "components/feed/core/v2/xsurface_datastore.h"
namespace feedui {
class StreamUpdate;
} // namespace feedui
namespace feed {
class SurfaceRenderer;
class MetricsReporter;
// Keeps the UI up to date by calling |FeedStreamSurface::StreamUpdate()|.
// Updates are triggered when |StreamModel| changes, or when loading state
// changes (for spinners and zero-state).
class SurfaceUpdater : public StreamModel::Observer,
public StreamSurfaceSet::Observer,
public XsurfaceDatastoreDataReader::Observer {
public:
explicit SurfaceUpdater(MetricsReporter* metrics_reporter,
XsurfaceDatastoreDataReader* global_datastore_slice,
StreamSurfaceSet* surfaces);
~SurfaceUpdater() override;
SurfaceUpdater(const SurfaceUpdater&) = delete;
SurfaceUpdater& operator=(const SurfaceUpdater&) = delete;
// Sets or unsets the model. When |model| is non-null, triggers the population
// of surfaces. When |model| is null, this does not send any updates to
// surfaces, so they will keep any content they may have been displaying
// before. We don't send a zero-state in this case, since we might want to
// immediately trigger a load.
void SetModel(StreamModel* model);
// StreamModel::Observer.
void OnUiUpdate(const StreamModel::UiUpdate& update) override;
// StreamSurfaceSet::Observer.
void SurfaceAdded(
SurfaceId surface_id,
SurfaceRenderer* renderer,
feedwire::DiscoverLaunchResult loading_not_allowed_reason) override;
void SurfaceRemoved(SurfaceId surface_id) override;
// XsurfaceDatastoreDataReader::Observer.
void DatastoreEntryUpdated(XsurfaceDatastoreDataReader* source,
const std::string& key) override;
void DatastoreEntryRemoved(XsurfaceDatastoreDataReader* source,
const std::string& key) override;
// Called to indicate the initial model load is in progress.
void LoadStreamStarted(bool manual_refreshing);
void LoadStreamComplete(bool success,
LoadStreamStatus load_stream_status,
feedwire::DiscoverLaunchResult launch_result);
// Called to indicate whether or not we are currently trying to load more
// content at the bottom of the stream.
void SetLoadingMore(bool is_loading);
// Returns the 0-based index of the slice in the stream, or -1 if the slice is
// not found. Ignores all non-content slices.
int GetSliceIndexFromSliceId(const std::string& slice_id);
void SetOfflinePageAvailability(const std::string& badge_id,
bool available_offline);
LaunchReliabilityLogger& launch_reliability_logger() {
return launch_reliability_logger_;
}
// State that together with |model_| determines what should be sent to a
// surface. |DrawState| is usually the same for all surfaces, except for the
// moment when a surface is first attached.
struct DrawState {
bool loading_more = false;
bool loading_initial = false;
feedui::ZeroStateSlice::Type zero_state_type =
feedui::ZeroStateSlice::UNKNOWN;
bool operator==(const DrawState& rhs) const;
};
private:
DrawState GetState() const;
bool ShouldSendStreamUpdate() const;
void SendStreamUpdateIfNeeded();
void SendStreamUpdate(
const std::vector<std::string>& updated_shared_state_ids);
void SendUpdateToSurface(SurfaceId surface_id,
SurfaceRenderer* surface,
const feedui::StreamUpdate& update);
void InsertDatastoreEntry(const std::string& key, const std::string& value);
void RemoveDatastoreEntry(const std::string& key);
// Owned by |FeedStream|.
raw_ptr<MetricsReporter> metrics_reporter_;
raw_ptr<StreamSurfaceSet> surfaces_;
// Per-StreamType xsurface data.
XsurfaceDatastoreSlice surface_data_slice_;
// Combines `surface_data_slice_`, and the global data.
XsurfaceDatastoreAggregate aggregate_data_;
// Members that affect what is sent to surfaces. A value change of these may
// require sending an update to surfaces.
bool loading_more_ = false;
bool loading_initial_ = false;
bool load_stream_failed_ = false;
LoadStreamStatus load_stream_status_ = LoadStreamStatus::kNoStatus;
// The |DrawState| when the last update was sent to all surfaces.
DrawState last_draw_state_;
// The set of content that has been sent to all attached surfaces.
base::flat_set<ContentRevision> sent_content_;
// Owned by |FeedStream|. Null when the model is not loaded.
raw_ptr<StreamModel, DanglingUntriaged> model_ = nullptr;
LaunchReliabilityLogger launch_reliability_logger_;
bool load_stream_started_ = false;
int current_load_more_indicator_id_ = 0;
};
} // namespace feed
#endif // COMPONENTS_FEED_CORE_V2_SURFACE_UPDATER_H_