blob: 74bdd6f9fab057aaedd1114dd878400c7742a396 [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;
Jon Miranda16ea1b12017-12-12 14:52:48 -080026import android.util.Log;
Jon Miranda16ea1b12017-12-12 14:52:48 -080027import android.view.LayoutInflater;
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -070028import android.view.SurfaceView;
Jon Miranda16ea1b12017-12-12 14:52:48 -080029import android.view.View;
Jon Miranda16ea1b12017-12-12 14:52:48 -080030import android.view.ViewGroup;
Santiago Etchebeherea5736dc2021-06-14 14:32:32 -070031import android.view.animation.Interpolator;
32import android.view.animation.PathInterpolator;
Tianguang Zhang893187f2021-05-07 22:14:04 +020033import android.widget.Button;
Jon Miranda16ea1b12017-12-12 14:52:48 -080034import android.widget.Toast;
35
Tianguang Zhang893187f2021-05-07 22:14:04 +020036import androidx.activity.OnBackPressedCallback;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070037import androidx.annotation.CallSuper;
Santiago Etchebehere32305d72019-03-25 14:32:40 -070038import androidx.annotation.IntDef;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070039import androidx.annotation.LayoutRes;
Santiago Etchebehere32305d72019-03-25 14:32:40 -070040import androidx.annotation.Nullable;
Santiago Etchebehere32305d72019-03-25 14:32:40 -070041import androidx.fragment.app.FragmentActivity;
42
Jon Miranda16ea1b12017-12-12 14:52:48 -080043import com.android.wallpaper.R;
Clément Julliard11ab2072019-04-23 10:04:15 -070044import com.android.wallpaper.model.LiveWallpaperInfo;
Jon Miranda16ea1b12017-12-12 14:52:48 -080045import com.android.wallpaper.model.WallpaperInfo;
Jon Miranda16ea1b12017-12-12 14:52:48 -080046import com.android.wallpaper.module.Injector;
47import com.android.wallpaper.module.InjectorProvider;
48import com.android.wallpaper.module.UserEventLogger;
Jon Miranda16ea1b12017-12-12 14:52:48 -080049import com.android.wallpaper.module.WallpaperPersister.Destination;
Jon Miranda16ea1b12017-12-12 14:52:48 -080050import com.android.wallpaper.module.WallpaperPreferences;
Santiago Etchebeheredf3e1162019-01-29 10:50:05 -080051import com.android.wallpaper.module.WallpaperSetter;
Tianguang Zhang893187f2021-05-07 22:14:04 +020052import com.android.wallpaper.util.FullScreenAnimation;
Tracy Zhoue4a5f262020-05-26 17:40:19 -070053import com.android.wallpaper.widget.BottomActionBar;
Chihhang Chuangf97f1592021-06-24 16:51:04 +080054import com.android.wallpaper.widget.BottomActionBar.BottomSheetContent;
55import com.android.wallpaper.widget.WallpaperInfoView;
Sunny Goyal8600a3f2018-08-15 12:48:01 -070056
Santiago Etchebehere3e452912021-06-07 18:10:30 -070057import com.google.android.material.tabs.TabLayout;
58
Jon Miranda16ea1b12017-12-12 14:52:48 -080059import java.util.Date;
60import java.util.List;
Santiago Etchebehere3e452912021-06-07 18:10:30 -070061import java.util.Optional;
Jon Miranda16ea1b12017-12-12 14:52:48 -080062
63/**
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -080064 * Base Fragment to display the UI for previewing an individual wallpaper
Jon Miranda16ea1b12017-12-12 14:52:48 -080065 */
Tracy Zhoue513aca2020-05-27 21:16:29 -070066public abstract class PreviewFragment extends AppbarFragment implements
Jon Miranda16ea1b12017-12-12 14:52:48 -080067 SetWallpaperDialogFragment.Listener, SetWallpaperErrorDialogFragment.Listener,
68 LoadWallpaperErrorDialogFragment.Listener {
69
Santiago Etchebeherea5736dc2021-06-14 14:32:32 -070070 public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
71
Jon Miranda16ea1b12017-12-12 14:52:48 -080072 /**
Santiago Etchebeheredc55b192019-11-08 13:56:52 -080073 * User can view wallpaper and attributions in full screen, but "Set wallpaper" button is
74 * hidden.
Jon Miranda16ea1b12017-12-12 14:52:48 -080075 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070076 static final int MODE_VIEW_ONLY = 0;
Jon Miranda16ea1b12017-12-12 14:52:48 -080077
78 /**
79 * User can view wallpaper and attributions in full screen and click "Set wallpaper" to set the
80 * wallpaper with pan and crop position to the device.
81 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -070082 static final int MODE_CROP_AND_SET_WALLPAPER = 1;
Santiago Etchebehere3e452912021-06-07 18:10:30 -070083 private Optional<Integer> mLastSelectedTabPositionOptional = Optional.empty();
Jon Miranda623e57e2018-01-05 16:33:30 -080084
85 /**
86 * Possible preview modes for the fragment.
87 */
88 @IntDef({
89 MODE_VIEW_ONLY,
90 MODE_CROP_AND_SET_WALLPAPER})
91 public @interface PreviewMode {
92 }
93
Clément Julliard11ab2072019-04-23 10:04:15 -070094 public static final String ARG_WALLPAPER = "wallpaper";
95 public static final String ARG_PREVIEW_MODE = "preview_mode";
Ching-Sung Lief59efa2020-06-05 22:41:43 +080096 public static final String ARG_VIEW_AS_HOME = "view_as_home";
Clément Julliard11ab2072019-04-23 10:04:15 -070097 public static final String ARG_TESTING_MODE_ENABLED = "testing_mode_enabled";
Santiago Etchebehere6fc434e2019-11-08 13:56:52 -080098
99 /**
100 * Creates and returns new instance of {@link ImagePreviewFragment} with the provided wallpaper
101 * set as an argument.
102 */
chihhangchuang7bd87702020-07-02 21:01:00 +0800103 public static PreviewFragment newInstance(WallpaperInfo wallpaperInfo, @PreviewMode int mode,
104 boolean viewAsHome, boolean testingModeEnabled) {
105 Bundle args = new Bundle();
Santiago Etchebehere6fc434e2019-11-08 13:56:52 -0800106 args.putParcelable(ARG_WALLPAPER, wallpaperInfo);
107 args.putInt(ARG_PREVIEW_MODE, mode);
Ching-Sung Lief59efa2020-06-05 22:41:43 +0800108 args.putBoolean(ARG_VIEW_AS_HOME, viewAsHome);
Santiago Etchebehere6fc434e2019-11-08 13:56:52 -0800109 args.putBoolean(ARG_TESTING_MODE_ENABLED, testingModeEnabled);
110
chihhangchuang13cb1fe2020-06-30 16:46:59 +0800111 PreviewFragment fragment = wallpaperInfo instanceof LiveWallpaperInfo
112 ? new LivePreviewFragment() : new ImagePreviewFragment();
Santiago Etchebehere6fc434e2019-11-08 13:56:52 -0800113 fragment.setArguments(args);
114 return fragment;
115 }
116
Jon Miranda16ea1b12017-12-12 14:52:48 -0800117 private static final String TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT =
118 "load_wallpaper_error_dialog";
Jon Miranda16ea1b12017-12-12 14:52:48 -0800119 private static final String TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT =
120 "set_wallpaper_error_dialog";
121 private static final int UNUSED_REQUEST_CODE = 1;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800122 private static final String TAG = "PreviewFragment";
Jon Miranda623e57e2018-01-05 16:33:30 -0800123
Jon Miranda16ea1b12017-12-12 14:52:48 -0800124 /**
125 * When true, enables a test mode of operation -- in which certain UI features are disabled to
126 * allow for UI tests to run correctly. Works around issue in ProgressDialog currently where the
127 * dialog constantly keeps the UI thread alive and blocks a test forever.
128 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700129 protected boolean mTestingModeEnabled;
Jon Miranda623e57e2018-01-05 16:33:30 -0800130
Clément Julliardea1638d2018-05-21 19:15:17 -0700131 protected WallpaperInfo mWallpaper;
Ching-Sung Lid2f46be2021-06-22 20:55:28 +0800132 protected WallpaperPreviewBitmapTransformation mPreviewBitmapTransformation;
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700133 protected WallpaperSetter mWallpaperSetter;
134 protected UserEventLogger mUserEventLogger;
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700135 protected BottomActionBar mBottomActionBar;
Ching-Sung Lid2f46be2021-06-22 20:55:28 +0800136 // For full screen animations.
137 protected View mRootView;
138 protected FullScreenAnimation mFullScreenAnimation;
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800139 @PreviewMode protected int mPreviewMode;
140 protected boolean mViewAsHome;
Ching-Sung Lid2f46be2021-06-22 20:55:28 +0800141
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800142 private OnBackPressedCallback mOnBackPressedCallback;
Chihhang Chuangf97f1592021-06-24 16:51:04 +0800143
Jon Miranda16ea1b12017-12-12 14:52:48 -0800144 /**
145 * Staged error dialog fragments that were unable to be shown when the hosting activity didn't
146 * allow committing fragment transactions.
147 */
148 private SetWallpaperErrorDialogFragment mStagedSetWallpaperErrorDialogFragment;
149 private LoadWallpaperErrorDialogFragment mStagedLoadWallpaperErrorDialogFragment;
150
Jon Miranda16ea1b12017-12-12 14:52:48 -0800151 @Override
152 public void onCreate(Bundle savedInstanceState) {
153 super.onCreate(savedInstanceState);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700154 Context appContext = getContext().getApplicationContext();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800155 Injector injector = InjectorProvider.getInjector();
156
Jon Miranda16ea1b12017-12-12 14:52:48 -0800157 mUserEventLogger = injector.getUserEventLogger(appContext);
158 mWallpaper = getArguments().getParcelable(ARG_WALLPAPER);
Ching-Sung Lid2f46be2021-06-22 20:55:28 +0800159 mPreviewBitmapTransformation = new WallpaperPreviewBitmapTransformation(
160 appContext, isRtl());
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700161
Jon Miranda16ea1b12017-12-12 14:52:48 -0800162 //noinspection ResourceType
163 mPreviewMode = getArguments().getInt(ARG_PREVIEW_MODE);
Ching-Sung Lief59efa2020-06-05 22:41:43 +0800164 mViewAsHome = getArguments().getBoolean(ARG_VIEW_AS_HOME);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800165 mTestingModeEnabled = getArguments().getBoolean(ARG_TESTING_MODE_ENABLED);
Santiago Etchebeheredf3e1162019-01-29 10:50:05 -0800166 mWallpaperSetter = new WallpaperSetter(injector.getWallpaperPersister(appContext),
167 injector.getPreferences(appContext), mUserEventLogger, mTestingModeEnabled);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800168
chihhangchuang13cb1fe2020-06-30 16:46:59 +0800169 Activity activity = getActivity();
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800170 List<String> attributions = getAttributions(activity);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800171 if (attributions.size() > 0 && attributions.get(0) != null) {
172 activity.setTitle(attributions.get(0));
173 }
174 }
175
176 @Override
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700177 @CallSuper
Jon Miranda16ea1b12017-12-12 14:52:48 -0800178 public View onCreateView(LayoutInflater inflater, ViewGroup container,
179 Bundle savedInstanceState) {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700180 View view = inflater.inflate(getLayoutResId(), container, false);
chihhangchuang13cb1fe2020-06-30 16:46:59 +0800181 setUpToolbar(view);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800182
Tianguang Zhang893187f2021-05-07 22:14:04 +0200183 mRootView = view;
184 mFullScreenAnimation = new FullScreenAnimation(view);
185
186 getActivity().getWindow().getDecorView().setOnApplyWindowInsetsListener(
187 (v, windowInsets) -> {
188 v.setPadding(
189 v.getPaddingLeft(),
190 0,
191 v.getPaddingRight(),
192 0);
193
194 mFullScreenAnimation.setWindowInsets(windowInsets);
195 mFullScreenAnimation.placeViews();
Chihhang Chuang530fc692021-05-15 14:19:36 +0800196 return windowInsets.consumeSystemWindowInsets();
Tianguang Zhang893187f2021-05-07 22:14:04 +0200197 }
198 );
199
Jon Miranda16ea1b12017-12-12 14:52:48 -0800200 return view;
201 }
202
Tracy Zhoue513aca2020-05-27 21:16:29 -0700203 @Override
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700204 protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
Kunhung Lic6701492021-01-28 17:35:56 +0800205 super.onBottomActionBarReady(bottomActionBar);
chihhangchuang13cb1fe2020-06-30 16:46:59 +0800206 mBottomActionBar = bottomActionBar;
Tianguang Zhang893187f2021-05-07 22:14:04 +0200207 mBottomActionBar.setActionClickListener(EDIT, (view) -> {
Chihhang Chuang60a5bc22021-05-14 23:00:01 +0800208 mFullScreenAnimation.startAnimation(/* toFullScreen= */ true);
Tianguang Zhang893187f2021-05-07 22:14:04 +0200209 mBottomActionBar.deselectAction(EDIT);
210 });
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800211 setFullScreenActions(mRootView.findViewById(R.id.fullscreen_buttons_container));
Tianguang Zhang893187f2021-05-07 22:14:04 +0200212
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800213 if (mOnBackPressedCallback == null) {
214 mOnBackPressedCallback = new OnBackPressedCallback(true) {
215 @Override
216 public void handleOnBackPressed() {
217 if (mFullScreenAnimation.isFullScreen()) {
218 mFullScreenAnimation.startAnimation(/* toFullScreen= */ false);
219 return;
220 }
221 if (mBottomActionBar != null && !mBottomActionBar.isBottomSheetCollapsed()) {
222 mBottomActionBar.collapseBottomSheetIfExpanded();
223 return;
224 }
225 getActivity().finish();
226 }
227 };
228 getActivity().getOnBackPressedDispatcher().addCallback(this, mOnBackPressedCallback);
229 }
230 }
231
232 protected void setFullScreenActions(View container) {
Chihhang Chuang18fb4ed2021-05-27 11:58:23 +0800233 // Update the button text for the current workspace visibility.
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800234 Button hideUiPreviewButton = container.findViewById(R.id.hide_ui_preview_button);
Chihhang Chuang18fb4ed2021-05-27 11:58:23 +0800235 hideUiPreviewButton.setText(mFullScreenAnimation.getWorkspaceVisibility()
236 ? R.string.hide_ui_preview_text
237 : R.string.show_ui_preview_text);
238 hideUiPreviewButton.setOnClickListener(
Tianguang Zhang893187f2021-05-07 22:14:04 +0200239 (button) -> {
240 boolean visible = mFullScreenAnimation.getWorkspaceVisibility();
Chihhang Chuang18fb4ed2021-05-27 11:58:23 +0800241 // Update the button text for the next workspace visibility.
Tianguang Zhang893187f2021-05-07 22:14:04 +0200242 ((Button) button).setText(visible
243 ? R.string.show_ui_preview_text
244 : R.string.hide_ui_preview_text);
245 mFullScreenAnimation.setWorkspaceVisibility(!visible);
246 }
247 );
Chihhang Chuang39ec8a02021-06-25 13:47:07 +0800248 container.findViewById(R.id.set_as_wallpaper_button).setOnClickListener(
249 this::onSetWallpaperClicked);
Tianguang Zhang893187f2021-05-07 22:14:04 +0200250
251 mFullScreenAnimation.ensureBottomActionBarIsCorrectlyLocated();
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700252 }
253
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800254 protected List<String> getAttributions(Context context) {
255 return mWallpaper.getAttributions(context);
256 }
257
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800258 @LayoutRes
259 protected abstract int getLayoutResId();
260
Santiago Etchebeheredbdfb662021-04-26 10:25:13 -0700261 protected WorkspaceSurfaceHolderCallback createWorkspaceSurfaceCallback(
262 SurfaceView workspaceSurface) {
263 return new WorkspaceSurfaceHolderCallback(workspaceSurface, getContext());
264 }
265
Jon Miranda16ea1b12017-12-12 14:52:48 -0800266 @Override
267 public void onResume() {
268 super.onResume();
269
Santiago Etchebehere1a0629a2019-05-22 16:41:58 -0700270 WallpaperPreferences preferences =
271 InjectorProvider.getInjector().getPreferences(getActivity());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800272 preferences.setLastAppActiveTimestamp(new Date().getTime());
273
Santiago Etchebehere1a0629a2019-05-22 16:41:58 -0700274 // Show the staged 'load wallpaper' or 'set wallpaper' error dialog fragments if there is
275 // one that was unable to be shown earlier when this fragment's hosting activity didn't
276 // allow committing fragment transactions.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800277 if (mStagedLoadWallpaperErrorDialogFragment != null) {
278 mStagedLoadWallpaperErrorDialogFragment.show(
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700279 requireFragmentManager(), TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800280 mStagedLoadWallpaperErrorDialogFragment = null;
281 }
282 if (mStagedSetWallpaperErrorDialogFragment != null) {
283 mStagedSetWallpaperErrorDialogFragment.show(
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700284 requireFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800285 mStagedSetWallpaperErrorDialogFragment = null;
286 }
287 }
288
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800289 protected abstract boolean isLoaded();
290
Jon Miranda16ea1b12017-12-12 14:52:48 -0800291 @Override
Clément Julliard11ab2072019-04-23 10:04:15 -0700292 public void onSet(int destination) {
293 setCurrentWallpaper(destination);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800294 }
295
296 @Override
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700297 public void onDialogDismissed(boolean withItemSelected) {
Chihhang Chuangca7c8252020-06-17 17:32:46 +0800298 mBottomActionBar.deselectAction(APPLY);
Tracy Zhoue4a5f262020-05-26 17:40:19 -0700299 }
300
301 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800302 public void onClickTryAgain(@Destination int wallpaperDestination) {
303 setCurrentWallpaper(wallpaperDestination);
304 }
305
306 @Override
307 public void onClickOk() {
Santiago Etchebeheref790d702018-06-07 13:04:13 -0700308 FragmentActivity activity = getActivity();
309 if (activity != null) {
310 activity.finish();
311 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800312 }
313
314 @Override
315 public void onDestroy() {
316 super.onDestroy();
Santiago Etchebeheredf3e1162019-01-29 10:50:05 -0800317 mWallpaperSetter.cleanUp();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800318 }
319
chihhangchuang7bd87702020-07-02 21:01:00 +0800320 @Override
321 public CharSequence getDefaultTitle() {
322 return getContext().getString(R.string.preview);
323 }
324
Santiago Etchebeheredc55b192019-11-08 13:56:52 -0800325 protected void onSetWallpaperClicked(View button) {
Santiago Etchebehereed9d1622019-12-05 15:19:22 -0800326 mWallpaperSetter.requestDestination(getActivity(), getFragmentManager(), this,
Santiago Etchebehere4ecb6aa2019-11-07 11:48:58 -0800327 mWallpaper instanceof LiveWallpaperInfo);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800328 }
329
Santiago Etchebehere3e452912021-06-07 18:10:30 -0700330 protected void setUpTabs(TabLayout tabs) {
Chihhang Chuang0f7efc42021-06-28 21:41:05 +0800331 tabs.addTab(tabs.newTab().setText(R.string.home_screen_message));
332 tabs.addTab(tabs.newTab().setText(R.string.lock_screen_message));
Santiago Etchebehere3e452912021-06-07 18:10:30 -0700333 tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
334 @Override
335 public void onTabSelected(TabLayout.Tab tab) {
336 mLastSelectedTabPositionOptional = Optional.of(tab.getPosition());
337 updateScreenPreview(/* isHomeSelected= */ tab.getPosition() == 0);
338 }
339
340 @Override
341 public void onTabUnselected(TabLayout.Tab tab) {}
342
343 @Override
344 public void onTabReselected(TabLayout.Tab tab) {}
345 });
346
347 // The TabLayout only contains below tabs
348 // 0. Home tab
349 // 1. Lock tab
350 int tabPosition = mLastSelectedTabPositionOptional.orElseGet(() -> mViewAsHome ? 0 : 1);
351 tabs.getTabAt(tabPosition).select();
352 updateScreenPreview(/* isHomeSelected= */ tabPosition == 0);
353 }
354
355 protected abstract void updateScreenPreview(boolean isHomeSelected);
356
Jon Miranda16ea1b12017-12-12 14:52:48 -0800357 /**
358 * Sets current wallpaper to the device based on current zoom and scroll state.
359 *
360 * @param destination The wallpaper destination i.e. home vs. lockscreen vs. both.
361 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700362 protected abstract void setCurrentWallpaper(@Destination int destination);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800363
Ching-Sung Lib5e9bd72020-06-15 14:10:55 +0800364 protected void finishActivity(boolean success) {
Chuck Liao507ce472020-08-17 16:29:24 +0800365 Activity activity = getActivity();
366 if (activity == null) {
367 return;
368 }
Ching-Sung Lib5e9bd72020-06-15 14:10:55 +0800369 if (success) {
370 try {
371 Toast.makeText(activity,
372 R.string.wallpaper_set_successfully_message, Toast.LENGTH_SHORT).show();
373 } catch (NotFoundException e) {
374 Log.e(TAG, "Could not show toast " + e);
375 }
376 activity.setResult(Activity.RESULT_OK);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800377 }
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700378 activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700379 activity.finish();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800380 }
381
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700382 protected void showSetWallpaperErrorDialog(@Destination int wallpaperDestination) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800383 SetWallpaperErrorDialogFragment newFragment = SetWallpaperErrorDialogFragment.newInstance(
384 R.string.set_wallpaper_error_message, wallpaperDestination);
385 newFragment.setTargetFragment(this, UNUSED_REQUEST_CODE);
386
Santiago Etchebehere25b7b272019-05-13 15:49:20 -0700387 // Show 'set wallpaper' error dialog now if it's safe to commit fragment transactions,
388 // otherwise stage it for later when the hosting activity is in a state to commit fragment
389 // transactions.
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700390 BasePreviewActivity activity = (BasePreviewActivity) requireActivity();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800391 if (activity.isSafeToCommitFragmentTransaction()) {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700392 newFragment.show(requireFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800393 } else {
394 mStagedSetWallpaperErrorDialogFragment = newFragment;
395 }
396 }
397
398 /**
Santiago Etchebehere25b7b272019-05-13 15:49:20 -0700399 * Shows 'load wallpaper' error dialog now or stage it to be shown when the hosting activity is
400 * in a state that allows committing fragment transactions.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800401 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700402 protected void showLoadWallpaperErrorDialog() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800403 LoadWallpaperErrorDialogFragment dialogFragment =
404 LoadWallpaperErrorDialogFragment.newInstance();
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700405 dialogFragment.setTargetFragment(this, UNUSED_REQUEST_CODE);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800406
407 // Show 'load wallpaper' error dialog now or stage it to be shown when the hosting
408 // activity is in a state that allows committing fragment transactions.
409 BasePreviewActivity activity = (BasePreviewActivity) getActivity();
410 if (activity != null && activity.isSafeToCommitFragmentTransaction()) {
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700411 dialogFragment.show(requireFragmentManager(), TAG_LOAD_WALLPAPER_ERROR_DIALOG_FRAGMENT);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800412 } else {
413 mStagedLoadWallpaperErrorDialogFragment = dialogFragment;
414 }
415 }
416
417 /**
Santiago Etchebehere25b7b272019-05-13 15:49:20 -0700418 * Returns whether layout direction is RTL (or false for LTR). Since native RTL layout support
419 * was added in API 17, returns false for versions lower than 17.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800420 */
Santiago Etchebehere6d3d1e62019-09-26 11:11:11 -0700421 protected boolean isRtl() {
Santiago Etchebehere25b7b272019-05-13 15:49:20 -0700422 return getResources().getConfiguration().getLayoutDirection()
423 == View.LAYOUT_DIRECTION_RTL;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800424 }
Chihhang Chuangf97f1592021-06-24 16:51:04 +0800425
426 protected final class WallpaperInfoContent extends BottomSheetContent<WallpaperInfoView> {
427
428 @Nullable private Intent mExploreIntent;
429 private CharSequence mActionLabel;
430
431 protected WallpaperInfoContent(Context context) {
432 super(context);
433 }
434
435 @Override
436 public int getViewId() {
437 return R.layout.wallpaper_info_view;
438 }
439
440 @Override
441 public void onViewCreated(WallpaperInfoView view) {
442 if (mWallpaper == null) {
443 return;
444 }
445
446 if (mActionLabel == null) {
447 setUpExploreIntentAndLabel(() -> populateWallpaperInfo(view));
448 } else {
449 populateWallpaperInfo(view);
450 }
451 }
452
453 private void setUpExploreIntentAndLabel(@Nullable Runnable callback) {
454 Context context = getContext();
455 if (context == null) {
456 return;
457 }
458
459 WallpaperInfoHelper.loadExploreIntent(context, mWallpaper,
460 (actionLabel, exploreIntent) -> {
461 mActionLabel = actionLabel;
462 mExploreIntent = exploreIntent;
463 if (callback != null) {
464 callback.run();
465 }
466 }
467 );
468 }
469
470 private void onExploreClicked(View button) {
471 Context context = getContext();
472 if (context == null) {
473 return;
474 }
475
476 mUserEventLogger.logActionClicked(mWallpaper.getCollectionId(context),
477 mWallpaper.getActionLabelRes(context));
478
479 startActivity(mExploreIntent);
480 }
481
482 private void populateWallpaperInfo(WallpaperInfoView view) {
483 view.populateWallpaperInfo(
484 mWallpaper,
485 mActionLabel,
486 WallpaperInfoHelper.shouldShowExploreButton(
487 getContext(), mExploreIntent),
488 this::onExploreClicked);
489 }
490 }
Santiago Etchebeheref4549ed2019-11-13 14:18:57 -0800491}