/* * Copyright (C) 2019 ByteDance Inc * * 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.bytedance.scene.ui; import android.app.Activity; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StyleRes; import com.bytedance.scene.Scene; import com.bytedance.scene.interfaces.PushOptions; import com.bytedance.scene.interfaces.PushResultCallback; import com.bytedance.scene.utlity.Utility; import java.util.ArrayList; import java.util.List; /** * Created by JiangQi on 9/3/18. */ public class SceneNavigator { public static interface NormalHook { Intent getIntent(Context context, int themeId, Class<? extends Scene> clazz, Bundle bundle); } public static interface ResultHook { Intent getIntent(Context context, int themeId, Class<? extends Scene> clazz, Bundle bundle, final PushResultCallback pushResultCallback); } private Context mContext; private Activity mHostActivity; @StyleRes private int mThemeResId = -1; private List<SceneNavigationContainer> mContainerList; public SceneNavigator(@NonNull Context context, @StyleRes int themeResId) { this(context, themeResId, new ArrayList<SceneNavigationContainer>()); } public SceneNavigator(@NonNull Context context, @StyleRes int themeResId, @Nullable SceneNavigationContainer container) { this(context, themeResId, toList(container)); } private static List<SceneNavigationContainer> toList(SceneNavigationContainer container) { List<SceneNavigationContainer> list = new ArrayList<>(); if (container != null) { list.add(container); } return list; } public SceneNavigator(@NonNull Context context, @StyleRes int themeResId, @Nullable List<SceneNavigationContainer> containerList) { mContext = context; mThemeResId = themeResId; while (context instanceof ContextWrapper) { if (context instanceof Activity) { mHostActivity = (Activity) context; break; } context = ((ContextWrapper) context).getBaseContext(); } this.mContainerList = containerList; } public void startScene(@NonNull Class<? extends Scene> clazz, @Nullable Bundle bundle) { startScene(clazz, bundle, null); } public void startScene(@NonNull Class<? extends Scene> clazz, @Nullable Bundle bundle, @Nullable NormalHook normalHook) { // Do nothing when the activity is destroying if (mHostActivity != null) { if (!Utility.isActivityStatusValid(mHostActivity)) { return; } } SceneNavigationContainer container = getVisibleSceneContainerActivity(); if (container != null) { container.getNavigationScene().push(clazz, bundle); return; } Intent intent = normalHook != null ? normalHook.getIntent(mContext, mThemeResId, clazz, bundle) : null; if (intent == null) { intent = SceneContainerActivity.newIntent(mContext, mThemeResId, clazz, bundle); } checkAndStart(intent); } public void startSceneForResult(@NonNull Class<? extends Scene> clazz, @Nullable Bundle bundle, @NonNull PushResultCallback pushResultCallback) { startSceneForResult(clazz, bundle, pushResultCallback, null); } public void startSceneForResult(@NonNull Class<? extends Scene> clazz, @Nullable Bundle bundle, @NonNull PushResultCallback pushResultCallback, @Nullable ResultHook resultHook) { // Do nothing when the activity is destroying if (mHostActivity != null) { if (!Utility.isActivityStatusValid(mHostActivity)) { pushResultCallback.onResult(null); return; } } SceneNavigationContainer container = getVisibleSceneContainerActivity(); if (container != null) { container.getNavigationScene().push(clazz, bundle, new PushOptions.Builder().setPushResultCallback(pushResultCallback).build()); return; } Intent intent = resultHook != null ? resultHook.getIntent(mContext, mThemeResId, clazz, bundle, pushResultCallback) : null; if (intent == null) { intent = SceneContainerActivity.newIntentForResult(mContext, mThemeResId, clazz, bundle, pushResultCallback); } checkAndStart(intent); } private SceneNavigationContainer getVisibleSceneContainerActivity() { SceneNavigationContainer target = null; if (mHostActivity instanceof SceneNavigationContainer) { target = ((SceneNavigationContainer) mHostActivity); if (!isSceneContainerValidToUse(target)) { target = null; } } if (target == null && mContainerList != null) { for (SceneNavigationContainer container : mContainerList) { if (isSceneContainerValidToUse(container)) { target = container; break; } } } if (target == null) { List<SceneContainerActivity> activityList = new ArrayList<>(SceneContainerActivity.sInstance); SceneContainerActivity currentTopContainerActivity = activityList.size() > 0 ? activityList.get(activityList.size() - 1) : null; if (currentTopContainerActivity != null && isSceneContainerValidToUse(currentTopContainerActivity) && Utility.isActivityStatusValid(currentTopContainerActivity)) { target = currentTopContainerActivity; } } return target; } protected boolean isSceneContainerValidToUse(SceneNavigationContainer container) { return container.isVisible() && container.getThemeId() == mThemeResId && container.getNavigationScene() != null; } private void checkAndStart(Intent intent) { if (mHostActivity != null) { mHostActivity.startActivity(intent); } else { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); } } }