blob: 53342d4b8157f2399857f77957fb2053c1948f19 [file] [log] [blame]
/*
* Copyright (C) 2022 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.wallpaper.picker;
import static android.view.View.VISIBLE;
import static com.android.wallpaper.util.LaunchSourceUtils.LAUNCH_SOURCE_LAUNCHER;
import static com.android.wallpaper.util.LaunchSourceUtils.LAUNCH_SOURCE_SETTINGS_HOMEPAGE;
import static com.android.wallpaper.util.LaunchSourceUtils.WALLPAPER_LAUNCH_SOURCE;
import static com.android.wallpaper.widget.FloatingSheet.INFORMATION;
import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED;
import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.WallpaperColors;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources.NotFoundException;
import android.graphics.drawable.Drawable;
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.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
import android.widget.Toolbar;
import androidx.annotation.CallSuper;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.view.AccessibilityDelegateCompat;
import androidx.core.view.ViewCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LifecycleOwnerKt;
import androidx.lifecycle.ViewModelProvider;
import com.android.wallpaper.R;
import com.android.wallpaper.model.LiveWallpaperInfo;
import com.android.wallpaper.model.SetWallpaperViewModel;
import com.android.wallpaper.model.WallpaperInfo;
import com.android.wallpaper.module.Injector;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.WallpaperPersister.Destination;
import com.android.wallpaper.module.WallpaperSetter;
import com.android.wallpaper.module.logging.UserEventLogger;
import com.android.wallpaper.util.PreviewUtils;
import com.android.wallpaper.util.ResourceUtils;
import com.android.wallpaper.widget.DuoTabs;
import com.android.wallpaper.widget.FloatingSheet;
import com.android.wallpaper.widget.WallpaperControlButtonGroup;
import com.android.wallpaper.widget.floatingsheetcontent.WallpaperInfoContent;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.transition.MaterialSharedAxis;
import java.util.List;
import kotlinx.coroutines.BuildersKt;
import kotlinx.coroutines.CoroutineStart;
import kotlinx.coroutines.Dispatchers;
/**
* Base Fragment to display the UI for previewing an individual wallpaper.
*/
public abstract class PreviewFragment extends Fragment implements WallpaperColorThemePreview {
public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
/**
* User can view wallpaper and attributions in full screen, but "Set wallpaper" button is
* hidden.
*/
public static final int MODE_VIEW_ONLY = 0;
/**
* User can view wallpaper and attributions in full screen and click "Set wallpaper" to set the
* wallpaper with pan and crop position to the device.
*/
public static final int MODE_CROP_AND_SET_WALLPAPER = 1;
/**
* Possible preview modes for the fragment.
*/
@IntDef({
MODE_VIEW_ONLY,
MODE_CROP_AND_SET_WALLPAPER})
public @interface PreviewMode {
}
public static final String ARG_IS_NEW_TASK = "is_new_task";
public static final String ARG_IS_ASSET_ID_PRESENT = "is_asset_id_present";
public static final String ARG_WALLPAPER = "wallpaper";
public static final String ARG_VIEW_AS_HOME = "view_as_home";
private static final String TAG = "PreviewFragment";
protected WallpaperInfo mWallpaper;
protected WallpaperSetter mWallpaperSetter;
protected ViewModelProvider mViewModelProvider;
protected WallpaperColors mWallpaperColors;
protected UserEventLogger mUserEventLogger;
private SetWallpaperViewModel mSetWallpaperViewModel;
// UI
private SurfaceView mWorkspaceSurface;
private WorkspaceSurfaceHolderCallback mWorkspaceSurfaceCallback;
private SurfaceView mLockSurface;
private WorkspaceSurfaceHolderCallback mLockSurfaceCallback;
private View mHideFloatingSheetTouchLayout;
private DuoTabs mOverlayTabs;
private @DuoTabs.Tab int mInitSelectedTab;
private View mExitFullPreviewButton;
protected View mSetWallpaperButton;
protected FrameLayout mSetWallpaperButtonContainer;
protected View mPreviewScrim;
protected Toolbar mToolbar;
protected WallpaperControlButtonGroup mWallpaperControlButtonGroup;
protected FloatingSheet mFloatingSheet;
protected TouchForwardingLayout mTouchForwardingLayout;
protected ProgressBar mProgressBar;
protected boolean mIsViewAsHome;
/**
* We create an instance of WallpaperInfo from CurrentWallpaperInfo when a user taps on
* the preview of a wallpapers in the wallpaper picker main screen. However, there are
* other instances as well in which an instance of the specific WallpaperInfo is created. This
* variable is used in order to identify whether the instance created has an assetId or not.
* This is needed for restricting the destination where a wallpaper can be set after editing
* it.
*/
protected boolean mIsAssetIdPresent;
/**
* True if the activity of this fragment is launched with {@link Intent#FLAG_ACTIVITY_NEW_TASK}.
*/
private boolean mIsNewTask;
// The system "short" animation time duration, in milliseconds. This
// duration is ideal for subtle animations or animations that occur
// very frequently.
private int mShortAnimTimeMillis;
private final BottomSheetBehavior.BottomSheetCallback mStandardFloatingSheetCallback =
new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@androidx.annotation.NonNull View bottomSheet,
int newState) {
if (newState == STATE_EXPANDED) {
mHideFloatingSheetTouchLayout.setVisibility(View.VISIBLE);
mTouchForwardingLayout.setVisibility(View.GONE);
}
if (newState == STATE_HIDDEN) {
mWallpaperControlButtonGroup.deselectAllFloatingSheetControlButtons();
mHideFloatingSheetTouchLayout.setVisibility(View.GONE);
mTouchForwardingLayout.setVisibility(VISIBLE);
mTouchForwardingLayout.requestFocus();
}
}
@Override
public void onSlide(@androidx.annotation.NonNull View bottomSheet,
float slideOffset) {
}
};
protected final BottomSheetBehavior.BottomSheetCallback
mShowOverlayOnHideFloatingSheetCallback =
new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@androidx.annotation.NonNull View bottomSheet,
int newState) {
if (newState == STATE_HIDDEN) {
hideScreenPreviewOverlay(/* hide= */false);
}
}
@Override
public void onSlide(@androidx.annotation.NonNull View bottomSheet,
float slideOffset) {
}
};
/**
* Sets current wallpaper to the device based on current zoom and scroll state.
*
* @param destination The wallpaper destination i.e. home vs. lockscreen vs. both.
*/
protected abstract void setWallpaper(@Destination int destination);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = requireArguments();
mWallpaper = args.getParcelable(ARG_WALLPAPER);
mIsViewAsHome = args.getBoolean(ARG_VIEW_AS_HOME);
mIsAssetIdPresent = args.getBoolean(ARG_IS_ASSET_ID_PRESENT);
mIsNewTask = args.getBoolean(ARG_IS_NEW_TASK);
mInitSelectedTab = mIsViewAsHome ? DuoTabs.TAB_SECONDARY : DuoTabs.TAB_PRIMARY;
Context appContext = requireContext().getApplicationContext();
Injector injector = InjectorProvider.getInjector();
mUserEventLogger = injector.getUserEventLogger();
mWallpaperSetter = new WallpaperSetter(injector.getWallpaperPersister(appContext),
injector.getPreferences(appContext), mUserEventLogger,
injector.getCurrentWallpaperInfoFactory(appContext));
mViewModelProvider = new ViewModelProvider(requireActivity());
mSetWallpaperViewModel = mViewModelProvider.get(SetWallpaperViewModel.class);
mSetWallpaperViewModel.getStatus().observe(requireActivity(), setWallpaperStatus -> {
switch (setWallpaperStatus) {
case SUCCESS:
onSetWallpaperSuccess();
break;
case ERROR:
showSetWallpaperErrorDialog();
break;
default:
// Do nothing when UNKNOWN or PENDING
}
});
mShortAnimTimeMillis = getResources().getInteger(android.R.integer.config_shortAnimTime);
setEnterTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward */ true));
setReturnTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward */ false));
setExitTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward */ true));
setReenterTransition(new MaterialSharedAxis(MaterialSharedAxis.X, /* forward */ false));
}
@Override
@CallSuper
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_wallpaper_preview, container, false);
// Progress indicator
mProgressBar = view.findViewById(R.id.action_progress);
// Toolbar
mToolbar = view.findViewById(R.id.toolbar);
setUpToolbar();
// TouchForwardingLayout
mTouchForwardingLayout = view.findViewById(R.id.touch_forwarding_layout);
mTouchForwardingLayout.setOnClickAccessibilityDescription(
R.string.hide_preview_controls_action);
// Preview overlay
mWorkspaceSurface = view.findViewById(R.id.workspace_surface);
mWorkspaceSurfaceCallback = new WorkspaceSurfaceHolderCallback(
mWorkspaceSurface,
new PreviewUtils(
requireContext(),
getString(R.string.grid_control_metadata_name)),
shouldApplyWallpaperColors());
// Hide the work space's bottom row initially to avoid overlapping with the overlay tabs.
mWorkspaceSurfaceCallback.setHideBottomRow(true);
mLockSurface = view.findViewById(R.id.lock_screen_overlay_surface);
mLockSurfaceCallback = new WorkspaceSurfaceHolderCallback(
mLockSurface,
new PreviewUtils(
requireContext().getApplicationContext(),
null,
getString(R.string.lock_screen_preview_provider_authority)),
shouldApplyWallpaperColors());
setUpScreenPreviewOverlay();
// Set wallpaper button
mSetWallpaperButtonContainer = view.findViewById(R.id.button_set_wallpaper_container);
mSetWallpaperButton = view.findViewById(R.id.button_set_wallpaper);
mSetWallpaperButtonContainer.setOnClickListener(
v -> showDestinationSelectionDialogForWallpaper(mWallpaper));
// Overlay tabs
mOverlayTabs = view.findViewById(R.id.overlay_tabs);
mOverlayTabs.setTabText(getString(R.string.lock_screen_message),
getString(R.string.home_screen_message));
mOverlayTabs.setOnTabSelectedListener(this::updateScreenPreviewOverlay);
mOverlayTabs.selectTab(mInitSelectedTab);
// Floating sheet and button control group
mFloatingSheet = view.findViewById(R.id.floating_sheet);
mHideFloatingSheetTouchLayout = view.findViewById(R.id.hide_floating_sheet_touch_layout);
mWallpaperControlButtonGroup = view.findViewById(R.id.wallpaper_control_button_group);
boolean shouldShowInformationFloatingSheet = shouldShowInformationFloatingSheet(mWallpaper);
setUpFloatingSheet(requireContext(), shouldShowInformationFloatingSheet);
if (shouldShowInformationFloatingSheet) {
mWallpaperControlButtonGroup.showButton(
WallpaperControlButtonGroup.INFORMATION,
getFloatingSheetControlButtonChangeListener(
WallpaperControlButtonGroup.INFORMATION,
INFORMATION));
}
mPreviewScrim = view.findViewById(R.id.preview_scrim);
mExitFullPreviewButton = view.findViewById(R.id.exit_full_preview_button);
mExitFullPreviewButton.setOnClickListener(v -> toggleWallpaperPreviewControl());
return view;
}
private void setUpToolbar() {
Activity activity = getActivity();
if (activity == null) {
return;
}
mToolbar.setTitle(R.string.preview);
mToolbar.setTitleTextColor(getResources().getColor(R.color.preview_toolbar_text_light));
mToolbar.setBackgroundResource(android.R.color.transparent);
activity.getWindow().setStatusBarColor(
getResources().getColor(android.R.color.transparent));
activity.getWindow().setNavigationBarColor(
getResources().getColor(android.R.color.transparent));
// The hosting activity needs to implement AppbarFragment.AppbarFragmentHost
AppbarFragment.AppbarFragmentHost host = (AppbarFragment.AppbarFragmentHost) activity;
if (host.isUpArrowSupported()) {
mToolbar.setNavigationIcon(getToolbarBackIcon());
mToolbar.setNavigationContentDescription(R.string.bottom_action_bar_back);
mToolbar.setNavigationOnClickListener(view -> {
host.onUpArrowPressed();
});
}
}
@Nullable
private Drawable getToolbarBackIcon() {
Drawable backIcon = ResourcesCompat.getDrawable(getResources(),
R.drawable.material_ic_arrow_back_black_24,
null);
if (backIcon == null) {
return null;
}
backIcon.setAutoMirrored(true);
backIcon.setTint(getResources().getColor(R.color.preview_toolbar_text_light));
return backIcon;
}
private void setUpScreenPreviewOverlay() {
int placeHolderColor = ResourceUtils.getColorAttr(requireContext(),
android.R.attr.colorBackground);
mWorkspaceSurface.setResizeBackgroundColor(placeHolderColor);
mWorkspaceSurface.setZOrderMediaOverlay(true);
mWorkspaceSurface.getHolder().addCallback(mWorkspaceSurfaceCallback);
mLockSurface.setResizeBackgroundColor(placeHolderColor);
mLockSurface.setZOrderMediaOverlay(true);
mLockSurface.getHolder().addCallback(mLockSurfaceCallback);
}
private boolean shouldShowInformationFloatingSheet(WallpaperInfo wallpaperInfo) {
List<String> attributions = wallpaperInfo.getAttributions(requireContext());
String actionUrl = wallpaperInfo.getActionUrl(requireContext());
boolean showAttribution = false;
for (String attr : attributions) {
if (attr != null && !attr.isEmpty()) {
showAttribution = true;
break;
}
}
boolean showActionUrl = actionUrl != null && !actionUrl.isEmpty();
return showAttribution || showActionUrl;
}
@SuppressLint("ClickableViewAccessibility")
private void setUpFloatingSheet(Context context, boolean shouldShowInformationFloatingSheet) {
setHideFloatingSheetLayoutAccessibilityAction();
mHideFloatingSheetTouchLayout.setContentDescription(
getString(R.string.preview_screen_description));
mHideFloatingSheetTouchLayout.setOnClickListener(v -> mFloatingSheet.collapse());
mHideFloatingSheetTouchLayout.setVisibility(View.GONE);
mFloatingSheet.addFloatingSheetCallback(mStandardFloatingSheetCallback);
mFloatingSheet.addFloatingSheetCallback(mShowOverlayOnHideFloatingSheetCallback);
if (shouldShowInformationFloatingSheet) {
mFloatingSheet.putFloatingSheetContent(INFORMATION,
new WallpaperInfoContent(context, mWallpaper));
}
}
protected CompoundButton.OnCheckedChangeListener getFloatingSheetControlButtonChangeListener(
@WallpaperControlButtonGroup.WallpaperControlType int wallpaperType,
@FloatingSheet.Companion.FloatingSheetContentType int floatingSheetType) {
return (buttonView, isChecked) -> {
if (isChecked) {
mWallpaperControlButtonGroup.deselectOtherFloatingSheetControlButtons(
wallpaperType);
if (mFloatingSheet.isFloatingSheetCollapsed()) {
if (floatingSheetType == INFORMATION) {
hideScreenPreviewOverlayKeepScrim();
} else {
hideScreenPreviewOverlay(/* hide= */true);
}
mFloatingSheet.updateContentView(floatingSheetType);
mFloatingSheet.expand();
} else {
mFloatingSheet.updateContentViewWithAnimation(floatingSheetType);
}
} else {
if (!mWallpaperControlButtonGroup.isFloatingSheetControlButtonSelected()) {
mFloatingSheet.collapse();
}
}
};
}
private void setHideFloatingSheetLayoutAccessibilityAction() {
ViewCompat.setAccessibilityDelegate(mHideFloatingSheetTouchLayout,
new AccessibilityDelegateCompat() {
@Override
public void onInitializeAccessibilityNodeInfo(View host,
AccessibilityNodeInfoCompat info) {
super.onInitializeAccessibilityNodeInfo(host, info);
CharSequence description = host.getResources().getString(
R.string.hide_wallpaper_info_action);
AccessibilityActionCompat clickAction = new AccessibilityActionCompat(
AccessibilityNodeInfoCompat.ACTION_CLICK, description);
info.addAction(clickAction);
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (mWallpaperSetter != null) {
mWallpaperSetter.cleanUp();
}
if (mWorkspaceSurfaceCallback != null) {
mWorkspaceSurfaceCallback.cleanUp();
}
if (mLockSurfaceCallback != null) {
mLockSurfaceCallback.cleanUp();
}
}
protected void onWallpaperColorsChanged(@Nullable WallpaperColors colors) {
// Early return to not block the instrumentation test.
if (InjectorProvider.getInjector().isInstrumentationTest()) {
return;
}
if (!shouldApplyWallpaperColors()) {
return;
}
mWallpaperColors = colors;
Context context = getContext();
if (context == null || colors == null) {
return;
}
// Apply the wallpaper color resources to the fragment context. So the views created by
// the context will apply the given wallpaper color.
BuildersKt.launch(
LifecycleOwnerKt.getLifecycleScope(getViewLifecycleOwner()),
Dispatchers.getIO(),
CoroutineStart.DEFAULT,
(coroutineScope, continuation) ->
InjectorProvider.getInjector().getWallpaperColorResources(colors,
context).apply(
context,
() -> {
requireActivity().runOnUiThread(() -> {
mSetWallpaperButton.setBackground(null);
mSetWallpaperButton.setBackgroundResource(
R.drawable.set_wallpaper_button_background);
mExitFullPreviewButton.setForeground(
AppCompatResources.getDrawable(context,
R.drawable.exit_full_preview_cross));
mWallpaperControlButtonGroup.updateBackgroundColor();
mOverlayTabs.updateBackgroundColor();
mFloatingSheet.setColor(context);
});
return null;
}, continuation
)
);
// Update the color theme for the home screen overlay
updateWorkspacePreview(mWorkspaceSurface, mWorkspaceSurfaceCallback, colors,
/* hideBottomRow= */ mOverlayTabs.getVisibility() == VISIBLE);
// Update the color theme for the lock screen overlay
updateWorkspacePreview(mLockSurface, mLockSurfaceCallback, colors,
/* hideBottomRow= */ mOverlayTabs.getVisibility() == VISIBLE);
}
private void updateScreenPreviewOverlay(@DuoTabs.Tab int tab) {
if (mWorkspaceSurface != null) {
mWorkspaceSurface.setVisibility(
tab == DuoTabs.TAB_SECONDARY ? View.VISIBLE : View.INVISIBLE);
mWorkspaceSurface.setZOrderMediaOverlay(tab == DuoTabs.TAB_SECONDARY);
}
if (mLockSurface != null) {
mLockSurface.setVisibility(
tab == DuoTabs.TAB_PRIMARY ? View.VISIBLE : View.INVISIBLE);
mLockSurface.setZOrderMediaOverlay(tab == DuoTabs.TAB_PRIMARY);
}
}
protected void toggleWallpaperPreviewControl() {
boolean wasVisible = mPreviewScrim.getVisibility() == VISIBLE;
mTouchForwardingLayout.setOnClickAccessibilityDescription(
wasVisible ? R.string.show_preview_controls_action
: R.string.hide_preview_controls_action);
animateWallpaperPreviewControl(wasVisible);
}
private void animateWallpaperPreviewControl(boolean hide) {
// When hiding the preview control, we should show the workspace bottom row components
hideBottomRow(!hide);
mPreviewScrim.animate()
.alpha(hide ? 0f : 1f)
.setDuration(mShortAnimTimeMillis)
.setListener(new ViewAnimatorListener(mPreviewScrim, hide));
mWallpaperControlButtonGroup.animate().alpha(hide ? 0f : 1f)
.setDuration(mShortAnimTimeMillis)
.setListener(new ViewAnimatorListener(mWallpaperControlButtonGroup, hide));
mOverlayTabs.animate().alpha(hide ? 0f : 1f)
.setDuration(mShortAnimTimeMillis)
.setListener(new ViewAnimatorListener(mOverlayTabs, hide));
mSetWallpaperButtonContainer.animate().alpha(hide ? 0f : 1f)
.setDuration(mShortAnimTimeMillis)
.setListener(new ViewAnimatorListener(mSetWallpaperButtonContainer, hide));
mToolbar.animate().alpha(hide ? 0f : 1f)
.setDuration(mShortAnimTimeMillis)
.setListener(new ViewAnimatorListener(mToolbar, hide));
// The show and hide of the button is the opposite of the wallpaper preview control
mExitFullPreviewButton.animate().alpha(!hide ? 0f : 1f)
.setDuration(mShortAnimTimeMillis)
.setListener(new ViewAnimatorListener(mExitFullPreviewButton, !hide));
}
private void hideBottomRow(boolean hide) {
if (mWorkspaceSurfaceCallback != null) {
Bundle data = new Bundle();
data.putBoolean(WorkspaceSurfaceHolderCallback.KEY_HIDE_BOTTOM_ROW, hide);
mWorkspaceSurfaceCallback.send(WorkspaceSurfaceHolderCallback.MESSAGE_ID_UPDATE_PREVIEW,
data);
}
}
protected void hideScreenPreviewOverlay(boolean hide) {
mPreviewScrim.setVisibility(hide ? View.INVISIBLE : View.VISIBLE);
mOverlayTabs.setVisibility(hide ? View.INVISIBLE : View.VISIBLE);
boolean isLockSelected = mOverlayTabs.getSelectedTab() == DuoTabs.TAB_PRIMARY;
if (isLockSelected) {
mLockSurface.setVisibility(hide ? View.INVISIBLE : View.VISIBLE);
mLockSurface.setZOrderMediaOverlay(!hide);
} else {
mWorkspaceSurface.setVisibility(hide ? View.INVISIBLE : View.VISIBLE);
mWorkspaceSurface.setZOrderMediaOverlay(!hide);
}
}
/**
* Hides or shows the overlay but leaves the scrim always visible.
*/
private void hideScreenPreviewOverlayKeepScrim() {
mPreviewScrim.setVisibility(VISIBLE);
mOverlayTabs.setVisibility(View.INVISIBLE);
boolean isLockSelected = mOverlayTabs.getSelectedTab() == DuoTabs.TAB_PRIMARY;
SurfaceView targetSurface = isLockSelected ? mLockSurface : mWorkspaceSurface;
targetSurface.setVisibility(View.INVISIBLE);
targetSurface.setZOrderMediaOverlay(false);
}
protected void onSetWallpaperSuccess() {
Activity activity = getActivity();
if (activity == null) {
return;
}
try {
Toast.makeText(activity, R.string.wallpaper_set_successfully_message,
Toast.LENGTH_SHORT).show();
} catch (NotFoundException e) {
Log.e(TAG, "Could not show toast " + e);
}
activity.setResult(Activity.RESULT_OK);
finishActivityWithFadeTransition();
// Start activity to go back to main screen.
if (mIsNewTask) {
Intent intent = new Intent(requireActivity(), TrampolinePickerActivity.class);
intent.putExtra(WALLPAPER_LAUNCH_SOURCE,
mIsViewAsHome ? LAUNCH_SOURCE_LAUNCHER : LAUNCH_SOURCE_SETTINGS_HOMEPAGE);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
protected void finishActivityWithFadeTransition() {
Activity activity = getActivity();
if (activity == null) {
return;
}
activity.finish();
}
private void showDestinationSelectionDialogForWallpaper(WallpaperInfo wallpaperInfo) {
// This logic is implemented for the editing of live wallpapers. The purpose is to
// restrict users to set the edited creative wallpaper only to the destination from
// where they originally started the editing process. For instance, if they began editing
// by clicking on the homescreen preview, they would be allowed to set the wallpaper on the
// homescreen and both the homescreen and lockscreen. On the other hand, if they initiated
// editing by clicking on the lockscreen preview, they would only be allowed to set the
// wallpaper on the lockscreen and both the homescreen and lockscreen. It's essential to
// note that this restriction only applies when the editing process is started by tapping
// on the preview available on the wallpaper picker home page.
boolean isLockOption = true;
boolean isHomeOption = true;
if (wallpaperInfo instanceof LiveWallpaperInfo) {
if (!mIsAssetIdPresent) {
isHomeOption = mIsViewAsHome;
isLockOption = !mIsViewAsHome;
}
}
mWallpaperSetter.requestDestination(getActivity(), getParentFragmentManager(),
destination -> {
mSetWallpaperViewModel.setDestination(destination);
setWallpaper(destination);
},
wallpaperInfo instanceof LiveWallpaperInfo, isHomeOption, isLockOption);
}
protected void showSetWallpaperErrorDialog() {
new AlertDialog.Builder(getActivity(), R.style.LightDialogTheme)
.setMessage(R.string.set_wallpaper_error_message)
.setPositiveButton(R.string.try_again, (dialogInterface, i) ->
setWallpaper(mSetWallpaperViewModel.getDestination())
)
.setNegativeButton(android.R.string.cancel, null)
.create()
.show();
}
protected void showLoadWallpaperErrorDialog() {
new AlertDialog.Builder(getActivity(), R.style.LightDialogTheme)
.setMessage(R.string.load_wallpaper_error_message)
.setPositiveButton(android.R.string.ok,
(dialogInterface, i) -> finishFragmentActivity())
.setOnDismissListener(dialog -> finishFragmentActivity())
.create()
.show();
}
private void finishFragmentActivity() {
FragmentActivity activity = getActivity();
if (activity != null) {
activity.finish();
}
}
private static class ViewAnimatorListener extends AnimatorListenerAdapter {
final View mView;
final boolean mHide;
private ViewAnimatorListener(View view, boolean hide) {
mView = view;
mHide = hide;
}
@Override
public void onAnimationStart(Animator animation) {
mView.setVisibility(VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
mView.setVisibility(mHide ? View.INVISIBLE : VISIBLE);
}
}
}