blob: e5f5df750347a25941dae9aa49e8735962369059 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* 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.android.customization.picker.grid;
import static android.app.Activity.RESULT_OK;
import static com.android.customization.picker.ViewOnlyFullPreviewActivity.SECTION_GRID;
import static com.android.customization.picker.grid.GridFullPreviewFragment.EXTRA_GRID_OPTION;
import static com.android.customization.picker.grid.GridFullPreviewFragment.EXTRA_WALLPAPER_INFO;
import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.widget.ContentLoadingProgressBar;
import androidx.recyclerview.widget.RecyclerView;
import com.android.customization.model.CustomizationManager.Callback;
import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
import com.android.customization.model.CustomizationOption;
import com.android.customization.model.grid.GridOption;
import com.android.customization.model.grid.GridOptionsManager;
import com.android.customization.module.ThemesUserEventLogger;
import com.android.customization.picker.ViewOnlyFullPreviewActivity;
import com.android.customization.picker.WallpaperPreviewer;
import com.android.customization.widget.OptionSelectorController;
import com.android.wallpaper.R;
import com.android.wallpaper.model.WallpaperInfo;
import com.android.wallpaper.module.CurrentWallpaperInfoFactory;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.picker.ToolbarFragment;
import com.android.wallpaper.widget.BottomActionBar;
import com.bumptech.glide.Glide;
import java.util.List;
/**
* Fragment that contains the UI for selecting and applying a GridOption.
*/
public class GridFragment extends ToolbarFragment {
private static final int FULL_PREVIEW_REQUEST_CODE = 1000;
private static final String KEY_STATE_SELECTED_OPTION = "GridFragment.selectedOption";
private static final String KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE =
"GridFragment.bottomActionBarVisible";
private static final String TAG = "GridFragment";
/**
* Interface to be implemented by an Activity hosting a {@link GridFragment}
*/
public interface GridFragmentHost {
GridOptionsManager getGridOptionsManager();
}
public static GridFragment newInstance(CharSequence title) {
GridFragment fragment = new GridFragment();
fragment.setArguments(ToolbarFragment.createArguments(title));
return fragment;
}
private WallpaperInfo mHomeWallpaper;
private RecyclerView mOptionsContainer;
private OptionSelectorController<GridOption> mOptionsController;
private GridOptionsManager mGridManager;
private GridOption mSelectedOption;
private ContentLoadingProgressBar mLoading;
private View mContent;
private View mError;
private BottomActionBar mBottomActionBar;
private ThemesUserEventLogger mEventLogger;
private GridOptionPreviewer mGridOptionPreviewer;
private final Callback mApplyGridCallback = new Callback() {
@Override
public void onSuccess() {
Toast.makeText(getContext(), R.string.applied_grid_msg, Toast.LENGTH_SHORT).show();
getActivity().overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
getActivity().finish();
}
@Override
public void onError(@Nullable Throwable throwable) {
// Since we disabled it when clicked apply button.
mBottomActionBar.enableActions();
mBottomActionBar.hide();
//TODO(chihhangchuang): handle
}
};
@Override
public void onAttach(Context context) {
super.onAttach(context);
mGridManager = ((GridFragmentHost) context).getGridOptionsManager();
mEventLogger = (ThemesUserEventLogger)
InjectorProvider.getInjector().getUserEventLogger(context);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(
R.layout.fragment_grid_picker, container, /* attachToRoot */ false);
setUpToolbar(view);
mContent = view.findViewById(R.id.content_section);
mOptionsContainer = view.findViewById(R.id.options_container);
mLoading = view.findViewById(R.id.loading_indicator);
mError = view.findViewById(R.id.error_section);
// Clear memory cache whenever grid fragment view is being loaded.
Glide.get(getContext()).clearMemory();
setUpOptions(savedInstanceState);
SurfaceView wallpaperSurface = view.findViewById(R.id.wallpaper_preview_surface);
WallpaperPreviewer wallpaperPreviewer = new WallpaperPreviewer(getLifecycle(),
getActivity(), view.findViewById(R.id.wallpaper_preview_image), wallpaperSurface);
// Loads current Wallpaper.
CurrentWallpaperInfoFactory factory = InjectorProvider.getInjector()
.getCurrentWallpaperFactory(getContext().getApplicationContext());
factory.createCurrentWallpaperInfos((homeWallpaper, lockWallpaper, presentationMode) -> {
mHomeWallpaper = homeWallpaper;
wallpaperPreviewer.setWallpaper(mHomeWallpaper, /* listener= */ null);
}, false);
mGridOptionPreviewer = new GridOptionPreviewer(mGridManager,
view.findViewById(R.id.grid_preview_container));
view.findViewById(R.id.grid_preview_card).setOnClickListener(v -> showFullPreview());
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
if (mGridOptionPreviewer != null) {
mGridOptionPreviewer.release();
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (mSelectedOption != null) {
outState.putParcelable(KEY_STATE_SELECTED_OPTION, mSelectedOption);
}
if (mBottomActionBar != null) {
outState.putBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE, mBottomActionBar.isVisible());
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FULL_PREVIEW_REQUEST_CODE && resultCode == RESULT_OK) {
applyGridOption(data.getParcelableExtra(EXTRA_GRID_OPTION));
}
}
@Override
protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
mBottomActionBar = bottomActionBar;
mBottomActionBar.showActionsOnly(APPLY);
mBottomActionBar.setActionClickListener(APPLY, unused -> applyGridOption(mSelectedOption));
}
private void applyGridOption(GridOption gridOption) {
mBottomActionBar.disableActions();
mGridManager.apply(gridOption, mApplyGridCallback);
}
private void setUpOptions(@Nullable Bundle savedInstanceState) {
hideError();
mLoading.show();
mGridManager.fetchOptions(new OptionsFetchedListener<GridOption>() {
@Override
public void onOptionsLoaded(List<GridOption> options) {
mLoading.hide();
mOptionsController = new OptionSelectorController<>(mOptionsContainer, options);
mOptionsController.initOptions(mGridManager);
// Find the selected Grid option.
GridOption previouslySelectedOption = null;
if (savedInstanceState != null) {
previouslySelectedOption = findEquivalent(
options, savedInstanceState.getParcelable(KEY_STATE_SELECTED_OPTION));
}
mSelectedOption = previouslySelectedOption != null
? previouslySelectedOption
: getActiveOption(options);
mOptionsController.setSelectedOption(mSelectedOption);
onOptionSelected(mSelectedOption);
restoreBottomActionBarVisibility(savedInstanceState);
mOptionsController.addListener(selectedOption -> {
onOptionSelected(selectedOption);
mBottomActionBar.show();
});
}
@Override
public void onError(@Nullable Throwable throwable) {
if (throwable != null) {
Log.e(TAG, "Error loading grid options", throwable);
}
showError();
}
}, false);
}
private GridOption getActiveOption(List<GridOption> options) {
return options.stream()
.filter(option -> option.isActive(mGridManager))
.findAny()
// For development only, as there should always be a grid set.
.orElse(options.get(0));
}
@Nullable
private GridOption findEquivalent(List<GridOption> options, GridOption target) {
return options.stream()
.filter(option -> option.equals(target))
.findAny()
.orElse(null);
}
private void hideError() {
mContent.setVisibility(View.VISIBLE);
mError.setVisibility(View.GONE);
}
private void showError() {
mLoading.hide();
mContent.setVisibility(View.GONE);
mError.setVisibility(View.VISIBLE);
}
private void onOptionSelected(CustomizationOption selectedOption) {
mSelectedOption = (GridOption) selectedOption;
mEventLogger.logGridSelected(mSelectedOption);
mGridOptionPreviewer.setGridOption(mSelectedOption);
}
private void restoreBottomActionBarVisibility(@Nullable Bundle savedInstanceState) {
boolean isBottomActionBarVisible = savedInstanceState != null
&& savedInstanceState.getBoolean(KEY_STATE_BOTTOM_ACTION_BAR_VISIBLE);
if (isBottomActionBarVisible) {
mBottomActionBar.show();
} else {
mBottomActionBar.hide();
}
}
private void showFullPreview() {
Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_WALLPAPER_INFO, mHomeWallpaper);
bundle.putParcelable(EXTRA_GRID_OPTION, mSelectedOption);
Intent intent = ViewOnlyFullPreviewActivity.newIntent(getContext(), SECTION_GRID, bundle);
startActivityForResult(intent, FULL_PREVIEW_REQUEST_CODE);
}
}