blob: 7c3aab9ba2adb1c09d20bd01ab0d5994045a7a60 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// 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/observer_list.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"
namespace feedui {
class StreamUpdate;
} // namespace feedui
namespace feed {
class FeedStreamSurface;
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:
explicit SurfaceUpdater(MetricsReporter* metrics_reporter);
~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
// immedately trigger a load.
void SetModel(StreamModel* model);
// StreamModel::Observer.
void OnUiUpdate(const StreamModel::UiUpdate& update) override;
// Signals from |FeedStream|.
void SurfaceAdded(FeedStreamSurface* surface,
feedwire::DiscoverLaunchResult loading_not_allowed_reason);
void SurfaceRemoved(FeedStreamSurface* surface);
// 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);
// Returns whether or not at least one surface is attached.
bool HasSurfaceAttached() const;
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(FeedStreamSurface* surface,
const feedui::StreamUpdate& update);
void InsertDatastoreEntry(const std::string& key, const std::string& value);
void RemoveDatastoreEntry(const std::string& key);
// 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_;
// XSurface datastore entries that should be sent to all surfaces.
// Cached here so that we don't need to recompute for a new surface.
std::map<std::string, std::string> xsurface_datastore_entries_;
// Owned by |FeedStream|. Null when the model is not loaded.
StreamModel* model_ = nullptr;
// Owned by |FeedStream|.
MetricsReporter* metrics_reporter_;
LaunchReliabilityLogger launch_reliability_logger_;
bool load_stream_started_ = false;
// Attached surfaces.
base::ObserverList<FeedStreamSurface> surfaces_;
};
} // namespace feed
#endif // COMPONENTS_FEED_CORE_V2_SURFACE_UPDATER_H_