blob: c91719e5b212af07af0654e0d8590a4b2f968a98 [file] [log] [blame]
Jon Miranda16ea1b12017-12-12 14:52:48 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.wallpaper.picker;
17
Tracy Zhoue4a5f262020-05-26 17:40:19 -070018import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY;
Tianguang Zhang893187f2021-05-07 22:14:04 +020019import static com.android.wallpaper.widget.BottomActionBar.BottomAction.EDIT;
Tracy Zhoue4a5f262020-05-26 17:40:19 -070020
Jon Miranda16ea1b12017-12-12 14:52:48 -080021import android.app.Activity;
Jon Miranda16ea1b12017-12-12 14:52:48 -080022import android.content.Context;
23import android.content.Intent;
Jon Miranda16ea1b12017-12-12 14:52:48 -080024import android.content.res.Resources.NotFoundException;
Jon Miranda16ea1b12017-12-12 14:52:48 -080025import android.os.Bundle;
Santiago Etchebehere60b55312021-08-20 18:06:28 -070026import android.os.Handler;
Jon Miranda16ea1b12017-12-12 14:52:48 -080027import android.util.Log;
Jon Miranda16ea1b12017-12-12 14:52:48 -080028import android.view.LayoutInflater;
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070029import android.view.SurfaceView;
Jon Miranda16ea1b12017-12-12 14:52:48 -080030import android.view.View;
Jon Miranda16ea1b12017-12-12 14:52:48 -080031import android.view.ViewGroup;
Santiago Etchebeherea5736dc2021-06-14 14:32:32 -070032import android.view.animation.Interpolator;
33import android.view.animation.PathInterpolator;
Tianguang Zhang893187f2021-05-07 22:14:04 +020034import android.widget.Button;
Jon Miranda16ea1b12017-12-12 14:52:48 -080035import android.widget.Toast;
36
Tianguang Zhang893187f2021-05-07 22:14:04 +020037import androidx.activity.OnBackPressedCallback;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070038import androidx.annotation.CallSuper;
Santiago Etchebehere32305d72019-03-25 14:32:40 -070039import androidx.annotation.IntDef;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070040import androidx.annotation.LayoutRes;
Santiago Etchebehere32305d72019-03-25 14:32:40 -070041import androidx.annotation.Nullable;
Santiago Etchebehere32305d72019-03-25 14:32:40 -070042import androidx.fragment.app.FragmentActivity;
Santiago Etchebehere60b55312021-08-20 18:06:28 -070043import androidx.lifecycle.ViewModelProvider;
Santiago Etchebehere32305d72019-03-25 14:32:40 -070044
Jon Miranda16ea1b12017-12-12 14:52:48 -080045import com.android.wallpaper.R;
Clément Julliard11ab2072019-04-23 10:04:15 -070046import com.android.wallpaper.model.LiveWallpaperInfo;
Santiago Etchebehere60b55312021-08-20 18:06:28 -070047import com.android.wallpaper.model.SetWallpaperViewModel;
Jon Miranda16ea1b12017-12-12 14:52:48 -080048import com.android.wallpaper.model.WallpaperInfo;
Jon Miranda16ea1b12017-12-12 14:52:48 -080049import com.android.wallpaper.module.Injector;
50import com.android.wallpaper.module.InjectorProvider;
51import com.android.wallpaper.module.UserEventLogger;
Jon Miranda16ea1b12017-12-12 14:52:48 -080052import com.android.wallpaper.module.WallpaperPersister.Destination;
Jon Miranda16ea1b12017-12-12 14:52:48 -080053import com.android.wallpaper.module.WallpaperPreferences;
Santiago Etchebeheredf3e1162019-01-29 10:50:05 -080054import com.android.wallpaper.module.WallpaperSetter;
Tianguang Zhang893187f2021-05-07 22:14:04 +020055import com.android.wallpaper.util.FullScreenAnimation;
Tracy Zhoue4a5f262020-05-26 17:40:19 -070056import com.android.wallpaper.widget.BottomActionBar;
Chihhang Chuangf97f1592021-06-24 16:51:04 +080057import com.android.wallpaper.widget.BottomActionBar.BottomSheetContent;
58import com.android.wallpaper.widget.WallpaperInfoView;
Sunny Goyal8600a3f2018-08-15 12:48:01 -070059
Santiago Etchebehere3e452912021-06-07 18:10:30 -070060import com.google.android.material.tabs.TabLayout;
61
Jon Miranda16ea1b12017-12-12 14:52:48 -080062import java.util.Date;
63import java.util.List;
Santiago Etchebehere3e452912021-06-07 18:10:30 -070064import java.util.Optional;
Jon Miranda16ea1b12017-12-12 14:52:48 -080065
66/**
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -080067 * Base Fragment to display the UI for previewing an individual wallpaper
Jon Miranda16ea1b12017-12-12 14:52:48 -080068 */
Tracy Zhoue513aca2020-05-27 21:16:29 -070069public abstract class PreviewFragment extends AppbarFragment implements
Jon Miranda16ea1b12017-12-12 14:52:48 -080070 SetWallpaperDialogFragment.Listener, SetWallpaperErrorDialogFragment.Listener,
71 LoadWallpaperErrorDialogFragment.Listener {
72
Santiago Etchebeherea5736dc2021-06-14 14:32:32 -070073 public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
74
Jon Miranda16ea1b12017-12-12 14:52:48 -080075 /**
Santiago Etchebeheredc55b192019-11-08 13:56:52 -080076 * User can view wallpaper and attributions in full screen, but "Set wallpaper" button is
77 * hidden.
Jon Miranda16ea1b12017-12-12 14:52:48 -080078 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070079 static final int MODE_VIEW_ONLY = 0;
Jon Miranda16ea1b12017-12-12 14:52:48 -080080
81 /**
82 * User can view wallpaper and attributions in full screen and click "Set wallpaper" to set the
83 * wallpaper with pan and crop position to the device.
84 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070085 static final int MODE_CROP_AND_SET_WALLPAPER = 1;
Jon Miranda623e57e2018-01-05 16:33:30 -080086
87 /**
88 * Possible preview modes for the fragment.
89 */
90 @IntDef({
91 MODE_VIEW_ONLY,
92 MODE_CROP_AND_SET_WALLPAPER})
93 public @interface PreviewMode {
94 }
95
Clément Julliard11ab2072019-04-23 10:04:15 -070096 public static final String ARG_WALLPAPER = "wallpaper";
97 public static final String ARG_PREVIEW_MODE = "preview_mode";
Ching-Sung Lief59efa2020-06-05 22:41:43 +080098 public static final String ARG_VIEW_AS_HOME = "view_as_home";
Clément Julliard11ab2072019-04-23 10:04:15 -070099 public static final String ARG_TESTING_MODE_ENABLED = "testing_mode_enabled";
Santiago Etchebehere6fc434e2019-11-08 13:56:52 -0800100
101 /**
102 * Creates and returns new instance of {@link ImagePreviewFragment} with the provided wallpaper
103 * set as an argument.
104 */
chihhangchuang7bd87702020-07-02 21:01:00 +0800105 public static PreviewFragment newInstance(WallpaperInfo wallpaperInfo, @PreviewMode int mode,
106 boolean viewAsHome, boolean testingModeEnabled) {
107 Bundle args = new Bundle();
Santiago Etchebehere6fc434e2019-11-08 13:56:52 -0800108 args.putParcelable(ARG_WALLPAPER, wallpaperInfo);
109 args.putInt(ARG_PREVIEW_MODE, mode);
Ching-Sung Lief59efa2020-06-05 22:41:43 +0800110 args.putBoolean(ARG_VIEW_AS_HOME, viewAsHome);
Santiago Etchebehere6fc434e2019-11-08 13:56:52 -0800111 args.putBoolean(ARG_TESTING_MODE_ENABLED, testingModeEnabled);
112
chihhangchuang13cb1fe2020-06-30 16:46:59 +0800113 PreviewFragment fragment = wallpaperInfo instanceof LiveWallpaperInfo
114 ? new LivePreviewFragment() : new ImagePreviewFragment();
Santiago Etchebehere6fc434e2019-11-08 13:56:52 -0800115 fragment.setArguments(args);
116 return fragment;
117 }
118
Jon Miranda16ea1b12017-12-12 14:52:48 -0800119 private static final String TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT =
120 "load_wallpaper_error_dialog";
Jon Miranda16ea1b12017-12-12 14:52:48 -0800121 private static final String TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT =
122 "set_wallpaper_error_dialog";
123 private static final int UNUSED_REQUEST_CODE = 1;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800124 private static final String TAG = "PreviewFragment";
Jon Miranda623e57e2018-01-05 16:33:30 -0800125
Jon Miranda16ea1b12017-12-12 14:52:48 -0800126 /**
127 * When true, enables a test mode of operation -- in which certain UI features are disabled to
128 * allow for UI tests to run correctly. Works around issue in ProgressDialog currently where the
129 * dialog constantly keeps the UI thread alive and blocks a test forever.
130 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700131 protected boolean mTestingModeEnabled;
Jon Miranda623e57e2018-01-05 16:33:30 -0800132
Clément Julliardea1638d2018-05-21 19:15:17 -0700133 protected WallpaperInfo mWallpaper;
Ching-Sung Lid2f46be2021-06-22 20:55:28 +0800134 protected WallpaperPreviewBitmapTransformation mPreviewBitmapTransformation;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700135 protected WallpaperSetter mWallpaperSetter;
136 protected UserEventLogger mUserEventLogger;
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700137 protected BottomActionBar mBottomActionBar;
Ching-Sung Lid2f46be2021-06-22 20:55:28 +0800138 // For full screen animations.
139 protected View mRootView;
140 protected FullScreenAnimation mFullScreenAnimation;
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800141 @PreviewMode protected int mPreviewMode;
142 protected boolean mViewAsHome;
Ching-Sung Lid2f46be2021-06-22 20:55:28 +0800143
Santiago Etchebehere60b55312021-08-20 18:06:28 -0700144 protected SetWallpaperViewModel mSetWallpaperViewModel;
145 protected ViewModelProvider mViewModelProvider;
zonghuayang2bfff842021-09-06 14:15:16 +0800146 protected Optional<Integer> mLastSelectedTabPositionOptional = Optional.empty();
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800147 private OnBackPressedCallback mOnBackPressedCallback;
Chihhang Chuangf97f1592021-06-24 16:51:04 +0800148
Jon Miranda16ea1b12017-12-12 14:52:48 -0800149 /**
150 * Staged error dialog fragments that were unable to be shown when the hosting activity didn't
151 * allow committing fragment transactions.
152 */
153 private SetWallpaperErrorDialogFragment mStagedSetWallpaperErrorDialogFragment;
154 private LoadWallpaperErrorDialogFragment mStagedLoadWallpaperErrorDialogFragment;
155
Jon Miranda16ea1b12017-12-12 14:52:48 -0800156 @Override
157 public void onCreate(Bundle savedInstanceState) {
158 super.onCreate(savedInstanceState);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700159 Context appContext = getContext().getApplicationContext();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800160 Injector injector = InjectorProvider.getInjector();
161
Jon Miranda16ea1b12017-12-12 14:52:48 -0800162 mUserEventLogger = injector.getUserEventLogger(appContext);
163 mWallpaper = getArguments().getParcelable(ARG_WALLPAPER);
Ching-Sung Lid2f46be2021-06-22 20:55:28 +0800164 mPreviewBitmapTransformation = new WallpaperPreviewBitmapTransformation(
165 appContext, isRtl());
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700166
Jon Miranda16ea1b12017-12-12 14:52:48 -0800167 //noinspection ResourceType
168 mPreviewMode = getArguments().getInt(ARG_PREVIEW_MODE);
Ching-Sung Lief59efa2020-06-05 22:41:43 +0800169 mViewAsHome = getArguments().getBoolean(ARG_VIEW_AS_HOME);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800170 mTestingModeEnabled = getArguments().getBoolean(ARG_TESTING_MODE_ENABLED);
Santiago Etchebeheredf3e1162019-01-29 10:50:05 -0800171 mWallpaperSetter = new WallpaperSetter(injector.getWallpaperPersister(appContext),
172 injector.getPreferences(appContext), mUserEventLogger, mTestingModeEnabled);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800173
Santiago Etchebehere60b55312021-08-20 18:06:28 -0700174 mViewModelProvider = new ViewModelProvider(requireActivity());
175 mSetWallpaperViewModel = mViewModelProvider.get(SetWallpaperViewModel.class);
176
chihhangchuang13cb1fe2020-06-30 16:46:59 +0800177 Activity activity = getActivity();
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800178 List<String> attributions = getAttributions(activity);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800179 if (attributions.size() > 0 && attributions.get(0) != null) {
180 activity.setTitle(attributions.get(0));
181 }
182 }
183
184 @Override
Kunhung Li529ee242021-09-07 17:11:03 +0800185 protected int getToolbarColorId() {
186 return android.R.color.transparent;
187 }
188
189 @Override
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700190 @CallSuper
Jon Miranda16ea1b12017-12-12 14:52:48 -0800191 public View onCreateView(LayoutInflater inflater, ViewGroup container,
192 Bundle savedInstanceState) {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700193 View view = inflater.inflate(getLayoutResId(), container, false);
chihhangchuang13cb1fe2020-06-30 16:46:59 +0800194 setUpToolbar(view);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800195
Tianguang Zhang893187f2021-05-07 22:14:04 +0200196 mRootView = view;
197 mFullScreenAnimation = new FullScreenAnimation(view);
198
199 getActivity().getWindow().getDecorView().setOnApplyWindowInsetsListener(
200 (v, windowInsets) -> {
201 v.setPadding(
202 v.getPaddingLeft(),
203 0,
204 v.getPaddingRight(),
205 0);
206
207 mFullScreenAnimation.setWindowInsets(windowInsets);
208 mFullScreenAnimation.placeViews();
Kunhung Li529ee242021-09-07 17:11:03 +0800209
210 // Update preview header's padding top to align status bar height.
211 View previewHeader = v.findViewById(R.id.preview_header);
212 previewHeader.setPadding(previewHeader.getPaddingLeft(),
213 mFullScreenAnimation.getStatusBarHeight(),
214 previewHeader.getPaddingRight(), previewHeader.getPaddingBottom());
215
Chihhang Chuang530fc692021-05-15 14:19:36 +0800216 return windowInsets.consumeSystemWindowInsets();
Tianguang Zhang893187f2021-05-07 22:14:04 +0200217 }
218 );
219
Jon Miranda16ea1b12017-12-12 14:52:48 -0800220 return view;
221 }
222
Tracy Zhoue513aca2020-05-27 21:16:29 -0700223 @Override
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700224 protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
Kunhung Lic6701492021-01-28 17:35:56 +0800225 super.onBottomActionBarReady(bottomActionBar);
chihhangchuang13cb1fe2020-06-30 16:46:59 +0800226 mBottomActionBar = bottomActionBar;
Tianguang Zhang893187f2021-05-07 22:14:04 +0200227 mBottomActionBar.setActionClickListener(EDIT, (view) -> {
Chihhang Chuang60a5bc22021-05-14 23:00:01 +0800228 mFullScreenAnimation.startAnimation(/* toFullScreen= */ true);
Tianguang Zhang893187f2021-05-07 22:14:04 +0200229 mBottomActionBar.deselectAction(EDIT);
230 });
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800231 setFullScreenActions(mRootView.findViewById(R.id.fullscreen_buttons_container));
Tianguang Zhang893187f2021-05-07 22:14:04 +0200232
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800233 if (mOnBackPressedCallback == null) {
234 mOnBackPressedCallback = new OnBackPressedCallback(true) {
235 @Override
236 public void handleOnBackPressed() {
237 if (mFullScreenAnimation.isFullScreen()) {
238 mFullScreenAnimation.startAnimation(/* toFullScreen= */ false);
239 return;
240 }
241 if (mBottomActionBar != null && !mBottomActionBar.isBottomSheetCollapsed()) {
242 mBottomActionBar.collapseBottomSheetIfExpanded();
243 return;
244 }
245 getActivity().finish();
246 }
247 };
248 getActivity().getOnBackPressedDispatcher().addCallback(this, mOnBackPressedCallback);
249 }
250 }
251
252 protected void setFullScreenActions(View container) {
Chihhang Chuang18fb4ed2021-05-27 11:58:23 +0800253 // Update the button text for the current workspace visibility.
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800254 Button hideUiPreviewButton = container.findViewById(R.id.hide_ui_preview_button);
Chihhang Chuang18fb4ed2021-05-27 11:58:23 +0800255 hideUiPreviewButton.setText(mFullScreenAnimation.getWorkspaceVisibility()
256 ? R.string.hide_ui_preview_text
257 : R.string.show_ui_preview_text);
258 hideUiPreviewButton.setOnClickListener(
Tianguang Zhang893187f2021-05-07 22:14:04 +0200259 (button) -> {
260 boolean visible = mFullScreenAnimation.getWorkspaceVisibility();
Chihhang Chuang18fb4ed2021-05-27 11:58:23 +0800261 // Update the button text for the next workspace visibility.
Tianguang Zhang893187f2021-05-07 22:14:04 +0200262 ((Button) button).setText(visible
263 ? R.string.show_ui_preview_text
264 : R.string.hide_ui_preview_text);
265 mFullScreenAnimation.setWorkspaceVisibility(!visible);
266 }
267 );
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800268 container.findViewById(R.id.set_as_wallpaper_button).setOnClickListener(
269 this::onSetWallpaperClicked);
Tianguang Zhang893187f2021-05-07 22:14:04 +0200270
271 mFullScreenAnimation.ensureBottomActionBarIsCorrectlyLocated();
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700272 }
273
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800274 protected List<String> getAttributions(Context context) {
275 return mWallpaper.getAttributions(context);
276 }
277
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800278 @LayoutRes
279 protected abstract int getLayoutResId();
280
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -0700281 protected WorkspaceSurfaceHolderCallback createWorkspaceSurfaceCallback(
282 SurfaceView workspaceSurface) {
283 return new WorkspaceSurfaceHolderCallback(workspaceSurface, getContext());
284 }
285
Jon Miranda16ea1b12017-12-12 14:52:48 -0800286 @Override
287 public void onResume() {
288 super.onResume();
289
Santiago Etchebehere1a0629a2019-05-22 16:41:58 -0700290 WallpaperPreferences preferences =
291 InjectorProvider.getInjector().getPreferences(getActivity());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800292 preferences.setLastAppActiveTimestamp(new Date().getTime());
293
Santiago Etchebehere1a0629a2019-05-22 16:41:58 -0700294 // Show the staged 'load wallpaper' or 'set wallpaper' error dialog fragments if there is
295 // one that was unable to be shown earlier when this fragment's hosting activity didn't
296 // allow committing fragment transactions.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800297 if (mStagedLoadWallpaperErrorDialogFragment != null) {
298 mStagedLoadWallpaperErrorDialogFragment.show(
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700299 requireFragmentManager(), TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800300 mStagedLoadWallpaperErrorDialogFragment = null;
301 }
302 if (mStagedSetWallpaperErrorDialogFragment != null) {
303 mStagedSetWallpaperErrorDialogFragment.show(
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700304 requireFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800305 mStagedSetWallpaperErrorDialogFragment = null;
306 }
Santiago Etchebehere60b55312021-08-20 18:06:28 -0700307
308 mSetWallpaperViewModel.getStatus().observe(requireActivity(), setWallpaperStatus -> {
309 switch (setWallpaperStatus) {
310 case SUCCESS:
311 // Give a few millis before finishing to allow for the dialog dismiss
312 // and animations to finish
313 Handler.getMain().postDelayed(() -> finishActivity(true), 300);
314 break;
315 case ERROR:
316 showSetWallpaperErrorDialog(mSetWallpaperViewModel.getDestination());
317 break;
318 default:
319 // Do nothing in this case, either status is pending, or unknown
320 }
321 });
Jon Miranda16ea1b12017-12-12 14:52:48 -0800322 }
323
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800324 protected abstract boolean isLoaded();
325
Jon Miranda16ea1b12017-12-12 14:52:48 -0800326 @Override
Clément Julliard11ab2072019-04-23 10:04:15 -0700327 public void onSet(int destination) {
Santiago Etchebehere60b55312021-08-20 18:06:28 -0700328 mSetWallpaperViewModel.setDestination(destination);
Clément Julliard11ab2072019-04-23 10:04:15 -0700329 setCurrentWallpaper(destination);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800330 }
331
332 @Override
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700333 public void onDialogDismissed(boolean withItemSelected) {
Chihhang Chuangca7c8252020-06-17 17:32:46 +0800334 mBottomActionBar.deselectAction(APPLY);
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700335 }
336
337 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800338 public void onClickTryAgain(@Destination int wallpaperDestination) {
Santiago Etchebehere60b55312021-08-20 18:06:28 -0700339 mSetWallpaperViewModel.setDestination(wallpaperDestination);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800340 setCurrentWallpaper(wallpaperDestination);
341 }
342
343 @Override
344 public void onClickOk() {
Santiago Etchebeheref790d702018-06-07 13:04:13 -0700345 FragmentActivity activity = getActivity();
346 if (activity != null) {
347 activity.finish();
348 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800349 }
350
351 @Override
352 public void onDestroy() {
353 super.onDestroy();
Santiago Etchebeheredf3e1162019-01-29 10:50:05 -0800354 mWallpaperSetter.cleanUp();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800355 }
356
chihhangchuang7bd87702020-07-02 21:01:00 +0800357 @Override
358 public CharSequence getDefaultTitle() {
359 return getContext().getString(R.string.preview);
360 }
361
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800362 protected void onSetWallpaperClicked(View button) {
Santiago Etchebehereed9d1622019-12-05 15:19:22 -0800363 mWallpaperSetter.requestDestination(getActivity(), getFragmentManager(), this,
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -0800364 mWallpaper instanceof LiveWallpaperInfo);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800365 }
366
Santiago Etchebehere3e452912021-06-07 18:10:30 -0700367 protected void setUpTabs(TabLayout tabs) {
Chihhang Chuang0f7efc42021-06-28 21:41:05 +0800368 tabs.addTab(tabs.newTab().setText(R.string.home_screen_message));
369 tabs.addTab(tabs.newTab().setText(R.string.lock_screen_message));
Santiago Etchebehere3e452912021-06-07 18:10:30 -0700370 tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
371 @Override
372 public void onTabSelected(TabLayout.Tab tab) {
373 mLastSelectedTabPositionOptional = Optional.of(tab.getPosition());
374 updateScreenPreview(/* isHomeSelected= */ tab.getPosition() == 0);
375 }
376
377 @Override
378 public void onTabUnselected(TabLayout.Tab tab) {}
379
380 @Override
381 public void onTabReselected(TabLayout.Tab tab) {}
382 });
383
384 // The TabLayout only contains below tabs
385 // 0. Home tab
386 // 1. Lock tab
387 int tabPosition = mLastSelectedTabPositionOptional.orElseGet(() -> mViewAsHome ? 0 : 1);
388 tabs.getTabAt(tabPosition).select();
389 updateScreenPreview(/* isHomeSelected= */ tabPosition == 0);
390 }
391
392 protected abstract void updateScreenPreview(boolean isHomeSelected);
393
Jon Miranda16ea1b12017-12-12 14:52:48 -0800394 /**
395 * Sets current wallpaper to the device based on current zoom and scroll state.
396 *
397 * @param destination The wallpaper destination i.e. home vs. lockscreen vs. both.
398 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700399 protected abstract void setCurrentWallpaper(@Destination int destination);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800400
Ching-Sung Lib5e9bd72020-06-15 14:10:55 +0800401 protected void finishActivity(boolean success) {
Chuck Liao507ce472020-08-17 16:29:24 +0800402 Activity activity = getActivity();
403 if (activity == null) {
404 return;
405 }
Ching-Sung Lib5e9bd72020-06-15 14:10:55 +0800406 if (success) {
407 try {
408 Toast.makeText(activity,
409 R.string.wallpaper_set_successfully_message, Toast.LENGTH_SHORT).show();
410 } catch (NotFoundException e) {
411 Log.e(TAG, "Could not show toast " + e);
412 }
413 activity.setResult(Activity.RESULT_OK);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800414 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700415 activity.finish();
Santiago Etchebehere60b55312021-08-20 18:06:28 -0700416 activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800417 }
418
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700419 protected void showSetWallpaperErrorDialog(@Destination int wallpaperDestination) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800420 SetWallpaperErrorDialogFragment newFragment = SetWallpaperErrorDialogFragment.newInstance(
421 R.string.set_wallpaper_error_message, wallpaperDestination);
422 newFragment.setTargetFragment(this, UNUSED_REQUEST_CODE);
423
Santiago Etchebehere25b7b272019-05-13 15:49:20 -0700424 // Show 'set wallpaper' error dialog now if it's safe to commit fragment transactions,
425 // otherwise stage it for later when the hosting activity is in a state to commit fragment
426 // transactions.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700427 BasePreviewActivity activity = (BasePreviewActivity) requireActivity();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800428 if (activity.isSafeToCommitFragmentTransaction()) {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700429 newFragment.show(requireFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800430 } else {
431 mStagedSetWallpaperErrorDialogFragment = newFragment;
432 }
433 }
434
435 /**
Santiago Etchebehere25b7b272019-05-13 15:49:20 -0700436 * Shows 'load wallpaper' error dialog now or stage it to be shown when the hosting activity is
437 * in a state that allows committing fragment transactions.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800438 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700439 protected void showLoadWallpaperErrorDialog() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800440 LoadWallpaperErrorDialogFragment dialogFragment =
441 LoadWallpaperErrorDialogFragment.newInstance();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700442 dialogFragment.setTargetFragment(this, UNUSED_REQUEST_CODE);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800443
444 // Show 'load wallpaper' error dialog now or stage it to be shown when the hosting
445 // activity is in a state that allows committing fragment transactions.
446 BasePreviewActivity activity = (BasePreviewActivity) getActivity();
447 if (activity != null && activity.isSafeToCommitFragmentTransaction()) {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700448 dialogFragment.show(requireFragmentManager(), TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800449 } else {
450 mStagedLoadWallpaperErrorDialogFragment = dialogFragment;
451 }
452 }
453
454 /**
Santiago Etchebehere25b7b272019-05-13 15:49:20 -0700455 * Returns whether layout direction is RTL (or false for LTR). Since native RTL layout support
456 * was added in API 17, returns false for versions lower than 17.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800457 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700458 protected boolean isRtl() {
Santiago Etchebehere25b7b272019-05-13 15:49:20 -0700459 return getResources().getConfiguration().getLayoutDirection()
460 == View.LAYOUT_DIRECTION_RTL;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800461 }
Chihhang Chuangf97f1592021-06-24 16:51:04 +0800462
463 protected final class WallpaperInfoContent extends BottomSheetContent<WallpaperInfoView> {
464
465 @Nullable private Intent mExploreIntent;
466 private CharSequence mActionLabel;
467
468 protected WallpaperInfoContent(Context context) {
469 super(context);
470 }
471
472 @Override
473 public int getViewId() {
474 return R.layout.wallpaper_info_view;
475 }
476
477 @Override
478 public void onViewCreated(WallpaperInfoView view) {
479 if (mWallpaper == null) {
480 return;
481 }
482
483 if (mActionLabel == null) {
484 setUpExploreIntentAndLabel(() -> populateWallpaperInfo(view));
485 } else {
486 populateWallpaperInfo(view);
487 }
488 }
489
490 private void setUpExploreIntentAndLabel(@Nullable Runnable callback) {
491 Context context = getContext();
492 if (context == null) {
493 return;
494 }
495
496 WallpaperInfoHelper.loadExploreIntent(context, mWallpaper,
497 (actionLabel, exploreIntent) -> {
498 mActionLabel = actionLabel;
499 mExploreIntent = exploreIntent;
500 if (callback != null) {
501 callback.run();
502 }
503 }
504 );
505 }
506
507 private void onExploreClicked(View button) {
508 Context context = getContext();
509 if (context == null) {
510 return;
511 }
512
513 mUserEventLogger.logActionClicked(mWallpaper.getCollectionId(context),
514 mWallpaper.getActionLabelRes(context));
515
516 startActivity(mExploreIntent);
517 }
518
519 private void populateWallpaperInfo(WallpaperInfoView view) {
520 view.populateWallpaperInfo(
521 mWallpaper,
522 mActionLabel,
523 WallpaperInfoHelper.shouldShowExploreButton(
524 getContext(), mExploreIntent),
525 this::onExploreClicked);
526 }
527 }
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800528}