blob: 07b3196b41989eb25993f340c5755e62ebb19e69 [file] [log] [blame]
// Copyright 2018 The Feed Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.android.libraries.feed.basicstream.internal.drivers;
import android.support.annotation.VisibleForTesting;
import com.google.android.libraries.feed.api.client.stream.Stream.ContentChangedListener;
import com.google.android.libraries.feed.api.host.action.ActionApi;
import com.google.android.libraries.feed.api.host.config.Configuration;
import com.google.android.libraries.feed.api.host.logging.BasicLoggingApi;
import com.google.android.libraries.feed.api.host.logging.InternalFeedError;
import com.google.android.libraries.feed.api.host.stream.TooltipApi;
import com.google.android.libraries.feed.api.internal.actionmanager.ActionManager;
import com.google.android.libraries.feed.api.internal.actionparser.ActionParserFactory;
import com.google.android.libraries.feed.api.internal.modelprovider.ModelChild;
import com.google.android.libraries.feed.api.internal.modelprovider.ModelChild.Type;
import com.google.android.libraries.feed.api.internal.modelprovider.ModelCursor;
import com.google.android.libraries.feed.api.internal.modelprovider.ModelFeature;
import com.google.android.libraries.feed.api.internal.modelprovider.ModelProvider;
import com.google.android.libraries.feed.basicstream.internal.pendingdismiss.ClusterPendingDismissHelper;
import com.google.android.libraries.feed.basicstream.internal.pendingdismiss.PendingDismissHandler;
import com.google.android.libraries.feed.basicstream.internal.viewloggingupdater.ViewLoggingUpdater;
import com.google.android.libraries.feed.common.concurrent.MainThreadRunner;
import com.google.android.libraries.feed.common.logging.Logger;
import com.google.android.libraries.feed.sharedstream.contextmenumanager.ContextMenuManager;
import com.google.android.libraries.feed.sharedstream.offlinemonitor.StreamOfflineMonitor;
import com.google.android.libraries.feed.sharedstream.pendingdismiss.PendingDismissCallback;
import com.google.search.now.ui.action.FeedActionProto.UndoAction;
/** {@link FeatureDriver} for Clusters. */
public class ClusterDriver implements FeatureDriver, ClusterPendingDismissHelper {
private static final String TAG = "ClusterDriver";
private final ActionApi actionApi;
private final ActionManager actionManager;
private final ActionParserFactory actionParserFactory;
private final BasicLoggingApi basicLoggingApi;
private final ModelFeature clusterModel;
private final ModelProvider modelProvider;
private final int position;
private final PendingDismissHandler pendingDismissHandler;
private final StreamOfflineMonitor streamOfflineMonitor;
private final ContentChangedListener contentChangedListener;
private final ContextMenuManager contextMenuManager;
private final MainThreadRunner mainThreadRunner;
private final Configuration configuration;
private final ViewLoggingUpdater viewLoggingUpdater;
private final TooltipApi tooltipApi;
/*@Nullable*/ private CardDriver cardDriver;
ClusterDriver(
ActionApi actionApi,
ActionManager actionManager,
ActionParserFactory actionParserFactory,
BasicLoggingApi basicLoggingApi,
ModelFeature clusterModel,
ModelProvider modelProvider,
int position,
PendingDismissHandler pendingDismissHandler,
StreamOfflineMonitor streamOfflineMonitor,
ContentChangedListener contentChangedListener,
ContextMenuManager contextMenuManager,
MainThreadRunner mainThreadRunner,
Configuration configuration,
ViewLoggingUpdater viewLoggingUpdater,
TooltipApi tooltipApi) {
this.actionApi = actionApi;
this.actionManager = actionManager;
this.actionParserFactory = actionParserFactory;
this.basicLoggingApi = basicLoggingApi;
this.clusterModel = clusterModel;
this.modelProvider = modelProvider;
this.position = position;
this.pendingDismissHandler = pendingDismissHandler;
this.streamOfflineMonitor = streamOfflineMonitor;
this.contentChangedListener = contentChangedListener;
this.contextMenuManager = contextMenuManager;
this.mainThreadRunner = mainThreadRunner;
this.configuration = configuration;
this.viewLoggingUpdater = viewLoggingUpdater;
this.tooltipApi = tooltipApi;
}
@Override
public void onDestroy() {
if (cardDriver != null) {
cardDriver.onDestroy();
}
}
@Override
/*@Nullable*/
public LeafFeatureDriver getLeafFeatureDriver() {
if (cardDriver == null) {
cardDriver = createCardChild(clusterModel);
}
if (cardDriver != null) {
return cardDriver.getLeafFeatureDriver();
}
return null;
}
/*@Nullable*/
private CardDriver createCardChild(ModelFeature clusterFeature) {
ModelCursor cursor = clusterFeature.getCursor();
// TODO: add change listener to clusterCursor.
ModelChild child;
while ((child = cursor.getNextItem()) != null) {
if (child.getType() != Type.FEATURE) {
basicLoggingApi.onInternalError(InternalFeedError.CLUSTER_CHILD_MISSING_FEATURE);
Logger.e(TAG, "Child of cursor is not a feature");
continue;
}
ModelFeature childModelFeature = child.getModelFeature();
if (!childModelFeature.getStreamFeature().hasCard()) {
basicLoggingApi.onInternalError(InternalFeedError.CLUSTER_CHILD_NOT_CARD);
Logger.e(TAG, "Content not card.");
continue;
}
return createCardDriver(childModelFeature);
}
return null;
}
@VisibleForTesting
CardDriver createCardDriver(ModelFeature content) {
return new CardDriver(
actionApi,
actionManager,
actionParserFactory,
basicLoggingApi,
content,
modelProvider,
position,
this,
streamOfflineMonitor,
contentChangedListener,
contextMenuManager,
mainThreadRunner,
configuration,
viewLoggingUpdater,
tooltipApi);
}
@Override
public void triggerPendingDismissForCluster(
UndoAction undoAction, PendingDismissCallback pendingDismissCallback) {
// Get the content id assoc with this ClusterDriver and pass the dismiss to the StreamDriver.
pendingDismissHandler.triggerPendingDismiss(
clusterModel.getStreamFeature().getContentId(), undoAction, pendingDismissCallback);
}
}