blob: 71d70e39e15da8a353febfa984f94dcac625a542 [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.individual;
17
Chuck Liao7dc21572020-05-14 18:37:36 +080018import static com.android.wallpaper.picker.WallpaperPickerDelegate.PREVIEW_WALLPAPER_REQUEST_CODE;
Chuck Liao69630f12020-03-05 19:01:25 +080019import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY;
Chuck Liao7dc21572020-05-14 18:37:36 +080020import static com.android.wallpaper.widget.BottomActionBar.BottomAction.EDIT;
chihhangchuang22aa0cc2020-03-25 19:12:42 +080021import static com.android.wallpaper.widget.BottomActionBar.BottomAction.INFORMATION;
Chuck Liao8ec38e02020-02-26 20:59:32 +080022import static com.android.wallpaper.widget.BottomActionBar.BottomAction.ROTATION;
23
Jon Miranda16ea1b12017-12-12 14:52:48 -080024import android.app.Activity;
25import android.app.ProgressDialog;
“Chuck7ef99722020-03-22 04:34:03 +080026import android.app.WallpaperManager;
Jon Miranda16ea1b12017-12-12 14:52:48 -080027import android.content.Context;
Chihhang Chuang85f099a2020-06-16 18:04:39 +080028import android.content.DialogInterface;
chihhangchuangc687d912020-05-04 14:33:05 +080029import android.content.Intent;
Santiago Etchebehereb1854472019-06-06 17:44:54 -070030import android.content.res.Configuration;
Jon Miranda16ea1b12017-12-12 14:52:48 -080031import android.content.res.Resources.NotFoundException;
32import android.graphics.Point;
Chuck Liaoba401232020-03-13 20:11:04 +080033import android.graphics.Rect;
Jon Miranda16ea1b12017-12-12 14:52:48 -080034import android.os.Build.VERSION;
35import android.os.Build.VERSION_CODES;
36import android.os.Bundle;
37import android.os.Handler;
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -070038import android.service.wallpaper.WallpaperService;
Jon Miranda16ea1b12017-12-12 14:52:48 -080039import android.util.Log;
40import android.view.LayoutInflater;
41import android.view.View;
42import android.view.ViewGroup;
Jon Miranda16ea1b12017-12-12 14:52:48 -080043import android.widget.Toast;
44
Santiago Etchebehereb1854472019-06-06 17:44:54 -070045import androidx.annotation.NonNull;
Chuck Liao69630f12020-03-05 19:01:25 +080046import androidx.annotation.Nullable;
Chuck Liaof6b4b192020-08-07 02:31:32 +080047import androidx.core.widget.ContentLoadingProgressBar;
Santiago Etchebeherefab49612019-01-15 12:22:42 -080048import androidx.fragment.app.DialogFragment;
Chuck Liao7e333722021-02-27 02:21:20 +080049import androidx.fragment.app.Fragment;
Santiago Etchebeherefab49612019-01-15 12:22:42 -080050import androidx.recyclerview.widget.GridLayoutManager;
51import androidx.recyclerview.widget.RecyclerView;
52import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
53import androidx.recyclerview.widget.RecyclerView.ViewHolder;
54
Jon Miranda16ea1b12017-12-12 14:52:48 -080055import com.android.wallpaper.R;
56import com.android.wallpaper.asset.Asset;
57import com.android.wallpaper.asset.Asset.DrawableLoadedListener;
Santiago Etchebehere8648bb82019-08-06 17:09:02 -070058import com.android.wallpaper.model.Category;
59import com.android.wallpaper.model.CategoryProvider;
60import com.android.wallpaper.model.CategoryReceiver;
Chuck Liao69630f12020-03-05 19:01:25 +080061import com.android.wallpaper.model.LiveWallpaperInfo;
Jon Miranda16ea1b12017-12-12 14:52:48 -080062import com.android.wallpaper.model.WallpaperCategory;
63import com.android.wallpaper.model.WallpaperInfo;
64import com.android.wallpaper.model.WallpaperReceiver;
65import com.android.wallpaper.model.WallpaperRotationInitializer;
66import com.android.wallpaper.model.WallpaperRotationInitializer.Listener;
67import com.android.wallpaper.model.WallpaperRotationInitializer.NetworkPreference;
Jon Miranda16ea1b12017-12-12 14:52:48 -080068import com.android.wallpaper.module.FormFactorChecker;
69import com.android.wallpaper.module.FormFactorChecker.FormFactor;
70import com.android.wallpaper.module.Injector;
71import com.android.wallpaper.module.InjectorProvider;
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -070072import com.android.wallpaper.module.PackageStatusNotifier;
chihhangchuangc687d912020-05-04 14:33:05 +080073import com.android.wallpaper.module.UserEventLogger;
Jon Miranda16ea1b12017-12-12 14:52:48 -080074import com.android.wallpaper.module.WallpaperChangedNotifier;
75import com.android.wallpaper.module.WallpaperPersister;
76import com.android.wallpaper.module.WallpaperPersister.Destination;
77import com.android.wallpaper.module.WallpaperPreferences;
Chuck Liao69630f12020-03-05 19:01:25 +080078import com.android.wallpaper.module.WallpaperSetter;
Jon Miranda16ea1b12017-12-12 14:52:48 -080079import com.android.wallpaper.picker.BaseActivity;
chihhangchuang3efb6832020-04-17 02:06:25 +080080import com.android.wallpaper.picker.BottomActionBarFragment;
Jon Miranda16ea1b12017-12-12 14:52:48 -080081import com.android.wallpaper.picker.CurrentWallpaperBottomSheetPresenter;
Chuck Liaob17d1502020-09-07 21:55:30 +080082import com.android.wallpaper.picker.FragmentTransactionChecker;
Santiago Etchebeherefab49612019-01-15 12:22:42 -080083import com.android.wallpaper.picker.MyPhotosStarter.MyPhotosStarterProvider;
Chuck Liao7dc21572020-05-14 18:37:36 +080084import com.android.wallpaper.picker.PreviewActivity;
Jon Miranda16ea1b12017-12-12 14:52:48 -080085import com.android.wallpaper.picker.RotationStarter;
Chuck Liao69630f12020-03-05 19:01:25 +080086import com.android.wallpaper.picker.SetWallpaperDialogFragment;
Jon Miranda16ea1b12017-12-12 14:52:48 -080087import com.android.wallpaper.picker.SetWallpaperErrorDialogFragment;
88import com.android.wallpaper.picker.StartRotationDialogFragment;
89import com.android.wallpaper.picker.StartRotationErrorDialogFragment;
chihhangchuangc687d912020-05-04 14:33:05 +080090import com.android.wallpaper.picker.WallpaperInfoHelper;
Jon Miranda16ea1b12017-12-12 14:52:48 -080091import com.android.wallpaper.picker.WallpapersUiContainer;
92import com.android.wallpaper.picker.individual.SetIndividualHolder.OnSetListener;
93import com.android.wallpaper.util.DiskBasedLogger;
Santiago Etchebehere53c63432020-05-07 18:55:35 -070094import com.android.wallpaper.util.SizeCalculator;
Chuck Liao8ec38e02020-02-26 20:59:32 +080095import com.android.wallpaper.widget.BottomActionBar;
chihhangchuang1a29e752020-04-28 18:22:53 +080096import com.android.wallpaper.widget.WallpaperInfoView;
Wesley.CW Wangdc68fde2020-06-15 19:12:33 +080097import com.android.wallpaper.widget.WallpaperPickerRecyclerViewAccessibilityDelegate;
98import com.android.wallpaper.widget.WallpaperPickerRecyclerViewAccessibilityDelegate.BottomSheetHost;
Sunny Goyal8600a3f2018-08-15 12:48:01 -070099
Jon Miranda16ea1b12017-12-12 14:52:48 -0800100import com.bumptech.glide.Glide;
101import com.bumptech.glide.MemoryCategory;
102
103import java.util.ArrayList;
104import java.util.Date;
105import java.util.List;
Chuck Liao11f4a762020-04-08 13:24:43 +0800106import java.util.Optional;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800107import java.util.Random;
108
109/**
110 * Displays the Main UI for picking an individual wallpaper image.
111 */
chihhangchuang3efb6832020-04-17 02:06:25 +0800112public class IndividualPickerFragment extends BottomActionBarFragment
Jon Miranda16ea1b12017-12-12 14:52:48 -0800113 implements RotationStarter, StartRotationErrorDialogFragment.Listener,
114 CurrentWallpaperBottomSheetPresenter.RefreshListener,
Chihhang Chuang85f099a2020-06-16 18:04:39 +0800115 SetWallpaperErrorDialogFragment.Listener, SetWallpaperDialogFragment.Listener,
116 StartRotationDialogFragment.Listener {
Chuck Liao46644b92020-06-08 14:20:50 +0800117
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800118 /**
119 * Position of a special tile that doesn't belong to an individual wallpaper of the category,
120 * such as "my photos" or "daily rotation".
121 */
122 static final int SPECIAL_FIXED_TILE_ADAPTER_POSITION = 0;
123 static final String ARG_CATEGORY_COLLECTION_ID = "category_collection_id";
124
Jon Miranda16ea1b12017-12-12 14:52:48 -0800125 private static final String TAG = "IndividualPickerFrgmnt";
Jon Miranda16ea1b12017-12-12 14:52:48 -0800126 private static final int UNUSED_REQUEST_CODE = 1;
127 private static final String TAG_START_ROTATION_DIALOG = "start_rotation_dialog";
128 private static final String TAG_START_ROTATION_ERROR_DIALOG = "start_rotation_error_dialog";
129 private static final String PROGRESS_DIALOG_NO_TITLE = null;
130 private static final boolean PROGRESS_DIALOG_INDETERMINATE = true;
131 private static final String TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT =
132 "individual_set_wallpaper_error_dialog";
Santiago Etchebehereb1854472019-06-06 17:44:54 -0700133 private static final String KEY_NIGHT_MODE = "IndividualPickerFragment.NIGHT_MODE";
Jon Miranda16ea1b12017-12-12 14:52:48 -0800134
Chuck Liao8ec38e02020-02-26 20:59:32 +0800135 /**
Chuck Liaof40063f2020-03-03 18:35:24 +0800136 * An interface for updating the thumbnail with the specific wallpaper.
137 */
138 public interface ThumbnailUpdater {
139 /**
140 * Updates the thumbnail with the specific wallpaper.
141 */
142 void updateThumbnail(WallpaperInfo wallpaperInfo);
143
144 /**
145 * Restores to the thumbnails of the wallpapers which were applied.
146 */
147 void restoreThumbnails();
148 }
149
“Chuck7ef99722020-03-22 04:34:03 +0800150 /**
151 * An interface for receiving the destination of the new applied wallpaper.
152 */
153 public interface WallpaperDestinationCallback {
154 /**
155 * Called when the destination of the wallpaper is set.
156 *
157 * @param destination the destination which a wallpaper may be set.
158 * See {@link Destination} for more details.
159 */
160 void onDestinationSet(@Destination int destination);
161 }
162
Chuck Liaob3829fb2020-04-01 00:47:50 +0800163 /**
164 * The listener which will be notified when the wallpaper is selected.
165 */
166 public interface WallpaperSelectedListener {
167 /**
168 * Called when the wallpaper is selected.
169 *
170 * @param position the position of the selected wallpaper
171 */
172 void onWallpaperSelected(int position);
173 }
174
Chuck Liaof6b4b192020-08-07 02:31:32 +0800175 /**
Chuck Liao7e333722021-02-27 02:21:20 +0800176 * Interface to be implemented by a Fragment(or an Activity) hosting
177 * a {@link IndividualPickerFragment}.
Chuck Liaof6b4b192020-08-07 02:31:32 +0800178 */
179 public interface IndividualPickerFragmentHost {
180 /**
181 * Sets the title in the toolbar.
182 */
183 void setToolbarTitle(CharSequence title);
184
185 /**
186 * Moves to the previous fragment.
187 */
188 void moveToPreviousFragment();
189 }
190
Ching-Sung Lied6560f2020-05-04 19:25:09 +0800191 WallpaperPersister mWallpaperPersister;
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800192 WallpaperPreferences mWallpaperPreferences;
193 WallpaperChangedNotifier mWallpaperChangedNotifier;
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800194 RecyclerView mImageGrid;
195 IndividualAdapter mAdapter;
196 WallpaperCategory mCategory;
197 WallpaperRotationInitializer mWallpaperRotationInitializer;
198 List<WallpaperInfo> mWallpapers;
199 Point mTileSizePx;
200 WallpapersUiContainer mWallpapersUiContainer;
201 @FormFactor
202 int mFormFactor;
203 PackageStatusNotifier mPackageStatusNotifier;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800204
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800205 Handler mHandler;
206 Random mRandom;
Chuck Liaof6b4b192020-08-07 02:31:32 +0800207 boolean mIsWallpapersReceived;
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800208
209 WallpaperChangedNotifier.Listener mWallpaperChangedListener =
210 new WallpaperChangedNotifier.Listener() {
211 @Override
212 public void onWallpaperChanged() {
213 if (mFormFactor != FormFactorChecker.FORM_FACTOR_DESKTOP) {
214 return;
215 }
216
217 ViewHolder selectedViewHolder = mImageGrid.findViewHolderForAdapterPosition(
218 mAdapter.mSelectedAdapterPosition);
219
220 // Null remote ID => My Photos wallpaper, so deselect whatever was previously selected.
221 if (mWallpaperPreferences.getHomeWallpaperRemoteId() == null) {
222 if (selectedViewHolder instanceof SelectableHolder) {
223 ((SelectableHolder) selectedViewHolder).setSelectionState(
224 SelectableHolder.SELECTION_STATE_DESELECTED);
225 }
226 } else {
227 mAdapter.updateSelectedTile(mAdapter.mPendingSelectedAdapterPosition);
228 }
229 }
230 };
231 PackageStatusNotifier.Listener mAppStatusListener;
Ching-Sung Li073812b2020-04-07 21:19:21 +0800232 BottomActionBar mBottomActionBar;
chihhangchuang1a29e752020-04-28 18:22:53 +0800233 WallpaperInfoView mWallpaperInfoView;
Ching-Sung Li073812b2020-04-07 21:19:21 +0800234 @Nullable WallpaperInfo mSelectedWallpaperInfo;
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800235
chihhangchuangc687d912020-05-04 14:33:05 +0800236 private UserEventLogger mUserEventLogger;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800237 private ProgressDialog mProgressDialog;
238 private boolean mTestingMode;
239 private CurrentWallpaperBottomSheetPresenter mCurrentWallpaperBottomSheetPresenter;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800240 private SetIndividualHolder mPendingSetIndividualHolder;
Chuck Liaof6b4b192020-08-07 02:31:32 +0800241 private ContentLoadingProgressBar mLoading;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800242
243 /**
244 * Staged error dialog fragments that were unable to be shown when the activity didn't allow
245 * committing fragment transactions.
246 */
247 private SetWallpaperErrorDialogFragment mStagedSetWallpaperErrorDialogFragment;
248 private StartRotationErrorDialogFragment mStagedStartRotationErrorDialogFragment;
249
Jon Miranda16ea1b12017-12-12 14:52:48 -0800250 private Runnable mCurrentWallpaperBottomSheetExpandedRunnable;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800251
252 /**
253 * Whether {@code mUpdateDailyWallpaperThumbRunnable} has been run at least once in this
254 * invocation of the fragment.
255 */
256 private boolean mWasUpdateRunnableRun;
257
258 /**
259 * A Runnable which regularly updates the thumbnail for the "Daily wallpapers" tile in desktop
260 * mode.
261 */
262 private Runnable mUpdateDailyWallpaperThumbRunnable = new Runnable() {
263 @Override
264 public void run() {
265 ViewHolder viewHolder = mImageGrid.findViewHolderForAdapterPosition(
266 SPECIAL_FIXED_TILE_ADAPTER_POSITION);
267 if (viewHolder instanceof DesktopRotationHolder) {
268 updateDesktopDailyRotationThumbnail((DesktopRotationHolder) viewHolder);
269 } else { // viewHolder is null
270 // If the rotation tile is unavailable (because user has scrolled down, causing the
271 // ViewHolder to be recycled), schedule the update for some time later. Once user scrolls up
272 // again, the ViewHolder will be re-bound and its thumbnail will be updated.
273 mHandler.postDelayed(mUpdateDailyWallpaperThumbRunnable,
274 DesktopRotationHolder.CROSSFADE_DURATION_MILLIS
275 + DesktopRotationHolder.CROSSFADE_DURATION_PAUSE_MILLIS);
276 }
277 }
278 };
279
Chuck Liao69630f12020-03-05 19:01:25 +0800280 private WallpaperSetter mWallpaperSetter;
“Chuckffd832c2020-03-22 02:15:58 +0800281 private WallpaperInfo mAppliedWallpaperInfo;
“Chuck7ef99722020-03-22 04:34:03 +0800282 private WallpaperManager mWallpaperManager;
283 private int mWallpaperDestination;
Chuck Liaob3829fb2020-04-01 00:47:50 +0800284 private WallpaperSelectedListener mWallpaperSelectedListener;
Chuck Liao8ec38e02020-02-26 20:59:32 +0800285
Jon Miranda16ea1b12017-12-12 14:52:48 -0800286 public static IndividualPickerFragment newInstance(String collectionId) {
287 Bundle args = new Bundle();
288 args.putString(ARG_CATEGORY_COLLECTION_ID, collectionId);
289
290 IndividualPickerFragment fragment = new IndividualPickerFragment();
291 fragment.setArguments(args);
292 return fragment;
293 }
294
“Chuck7ef99722020-03-22 04:34:03 +0800295 /**
296 * Highlights the applied wallpaper (if it exists) according to the destination a wallpaper
297 * would be set.
298 *
299 * @param wallpaperDestination the destination a wallpaper would be set.
300 * It will be either {@link Destination#DEST_HOME_SCREEN}
301 * or {@link Destination#DEST_LOCK_SCREEN}.
302 */
303 public void highlightAppliedWallpaper(@Destination int wallpaperDestination) {
304 mWallpaperDestination = wallpaperDestination;
Chuck Liao11f4a762020-04-08 13:24:43 +0800305 if (mWallpapers != null) {
306 refreshAppliedWallpaper();
“Chuck7ef99722020-03-22 04:34:03 +0800307 }
308 }
309
Jon Miranda16ea1b12017-12-12 14:52:48 -0800310 private void updateDesktopDailyRotationThumbnail(DesktopRotationHolder holder) {
311 int wallpapersIndex = mRandom.nextInt(mWallpapers.size());
312 Asset newThumbnailAsset = mWallpapers.get(wallpapersIndex).getThumbAsset(
313 getActivity());
314 holder.updateThumbnail(newThumbnailAsset, new DrawableLoadedListener() {
315 @Override
316 public void onDrawableLoaded() {
317 if (getActivity() == null) {
318 return;
319 }
320
321 // Schedule the next update of the thumbnail.
322 int delayMillis = DesktopRotationHolder.CROSSFADE_DURATION_MILLIS
323 + DesktopRotationHolder.CROSSFADE_DURATION_PAUSE_MILLIS;
324 mHandler.postDelayed(mUpdateDailyWallpaperThumbRunnable, delayMillis);
325 }
326 });
327 }
328
329 @Override
330 public void onCreate(Bundle savedInstanceState) {
331 super.onCreate(savedInstanceState);
332
333 Injector injector = InjectorProvider.getInjector();
334 Context appContext = getContext().getApplicationContext();
335 mWallpaperPreferences = injector.getPreferences(appContext);
336
337 mWallpaperChangedNotifier = WallpaperChangedNotifier.getInstance();
338 mWallpaperChangedNotifier.registerListener(mWallpaperChangedListener);
339
“Chuck7ef99722020-03-22 04:34:03 +0800340 mWallpaperManager = WallpaperManager.getInstance(appContext);
341
Jon Miranda16ea1b12017-12-12 14:52:48 -0800342 mFormFactor = injector.getFormFactorChecker(appContext).getFormFactor();
343
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700344 mPackageStatusNotifier = injector.getPackageStatusNotifier(appContext);
345
chihhangchuangc687d912020-05-04 14:33:05 +0800346 mUserEventLogger = injector.getUserEventLogger(appContext);
347
“Chuckffd832c2020-03-22 02:15:58 +0800348 mWallpaperPersister = injector.getWallpaperPersister(appContext);
Chuck Liao69630f12020-03-05 19:01:25 +0800349 mWallpaperSetter = new WallpaperSetter(
“Chuckffd832c2020-03-22 02:15:58 +0800350 mWallpaperPersister,
Chuck Liao69630f12020-03-05 19:01:25 +0800351 injector.getPreferences(appContext),
352 injector.getUserEventLogger(appContext),
353 false);
354
Jon Miranda16ea1b12017-12-12 14:52:48 -0800355 mWallpapers = new ArrayList<>();
356 mRandom = new Random();
357 mHandler = new Handler();
358
Santiago Etchebehereb1854472019-06-06 17:44:54 -0700359 // Clear Glide's cache if night-mode changed to ensure thumbnails are reloaded
360 if (savedInstanceState != null && (savedInstanceState.getInt(KEY_NIGHT_MODE)
361 != (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK))) {
362 Glide.get(getContext()).clearMemory();
363 }
364
Santiago Etchebehere8648bb82019-08-06 17:09:02 -0700365 CategoryProvider categoryProvider = injector.getCategoryProvider(appContext);
366 categoryProvider.fetchCategories(new CategoryReceiver() {
367 @Override
368 public void onCategoryReceived(Category category) {
369 // Do nothing.
370 }
371
372 @Override
373 public void doneFetchingCategories() {
Chuck Liao7e36d172020-09-18 01:09:17 +0800374 Category category = categoryProvider.getCategory(
Santiago Etchebehere8648bb82019-08-06 17:09:02 -0700375 getArguments().getString(ARG_CATEGORY_COLLECTION_ID));
Chuck Liaof44433e2020-09-21 22:58:26 +0800376 if (category != null && !(category instanceof WallpaperCategory)) {
Chuck Liao7e36d172020-09-18 01:09:17 +0800377 return;
378 }
379 mCategory = (WallpaperCategory) category;
Santiago Etchebehere8648bb82019-08-06 17:09:02 -0700380 if (mCategory == null) {
381 DiskBasedLogger.e(TAG, "Failed to find the category.", getContext());
382
383 // The absence of this category in the CategoryProvider indicates a broken
384 // state, see b/38030129. Hence, finish the activity and return.
Chuck Liaof6b4b192020-08-07 02:31:32 +0800385 getIndividualPickerFragmentHost().moveToPreviousFragment();
386 Toast.makeText(getContext(), R.string.collection_not_exist_msg,
387 Toast.LENGTH_SHORT).show();
Santiago Etchebehere8648bb82019-08-06 17:09:02 -0700388 return;
389 }
390 onCategoryLoaded();
391 }
392 }, false);
393 }
394
Chuck Liaof6b4b192020-08-07 02:31:32 +0800395
Santiago Etchebehere8648bb82019-08-06 17:09:02 -0700396 protected void onCategoryLoaded() {
Chuck Liao7e36d172020-09-18 01:09:17 +0800397 if (getIndividualPickerFragmentHost() == null) {
398 return;
399 }
Chuck Liaof6b4b192020-08-07 02:31:32 +0800400 getIndividualPickerFragmentHost().setToolbarTitle(mCategory.getTitle());
Santiago Etchebehere8648bb82019-08-06 17:09:02 -0700401 mWallpaperRotationInitializer = mCategory.getWallpaperRotationInitializer();
Chuck Liao58e4a1c2020-05-22 11:35:35 +0800402 // Avoids the "rotation" action is not shown correctly
403 // in a rare case : onCategoryLoaded() is called after onBottomActionBarReady().
404 if (isRotationEnabled() && mBottomActionBar != null
405 && !mBottomActionBar.areActionsShown(ROTATION)) {
406 mBottomActionBar.showActions(ROTATION);
407 }
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700408 fetchWallpapers(false);
409
410 if (mCategory.supportsThirdParty()) {
411 mAppStatusListener = (packageName, status) -> {
412 if (status != PackageStatusNotifier.PackageStatus.REMOVED ||
413 mCategory.containsThirdParty(packageName)) {
414 fetchWallpapers(true);
415 }
416 };
417 mPackageStatusNotifier.addListener(mAppStatusListener,
418 WallpaperService.SERVICE_INTERFACE);
419 }
Santiago Etchebehere8648bb82019-08-06 17:09:02 -0700420
Santiago Etchebehere460fbcb2019-08-20 11:47:30 -0700421 maybeSetUpImageGrid();
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700422 }
423
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800424 void fetchWallpapers(boolean forceReload) {
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700425 mWallpapers.clear();
Chuck Liaof6b4b192020-08-07 02:31:32 +0800426 mIsWallpapersReceived = false;
427 updateLoading();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800428 mCategory.fetchWallpapers(getActivity().getApplicationContext(), new WallpaperReceiver() {
429 @Override
430 public void onWallpapersReceived(List<WallpaperInfo> wallpapers) {
Chuck Liaof6b4b192020-08-07 02:31:32 +0800431 mIsWallpapersReceived = true;
432 updateLoading();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800433 for (WallpaperInfo wallpaper : wallpapers) {
434 mWallpapers.add(wallpaper);
435 }
436
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700437 // Wallpapers may load after the adapter is initialized, in which case we have
438 // to explicitly notify that the data set has changed.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800439 if (mAdapter != null) {
440 mAdapter.notifyDataSetChanged();
441 }
442
443 if (mWallpapersUiContainer != null) {
444 mWallpapersUiContainer.onWallpapersReady();
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700445 } else {
446 if (wallpapers.isEmpty()) {
447 // If there are no more wallpapers and we're on phone, just finish the
448 // Activity.
449 Activity activity = getActivity();
450 if (activity != null
451 && mFormFactor == FormFactorChecker.FORM_FACTOR_MOBILE) {
452 activity.finish();
453 }
454 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800455 }
456 }
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700457 }, forceReload);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800458 }
459
Chuck Liaof6b4b192020-08-07 02:31:32 +0800460 void updateLoading() {
461 if (mLoading == null) {
462 return;
463 }
464
465 if (mIsWallpapersReceived) {
466 mLoading.hide();
467 } else {
468 mLoading.show();
469 }
470 }
471
Jon Miranda16ea1b12017-12-12 14:52:48 -0800472 @Override
Santiago Etchebehereb1854472019-06-06 17:44:54 -0700473 public void onSaveInstanceState(@NonNull Bundle outState) {
474 super.onSaveInstanceState(outState);
Santiago Etchebehere0ec065c2019-06-13 11:30:21 -0700475 outState.putInt(KEY_NIGHT_MODE,
Santiago Etchebehereb1854472019-06-06 17:44:54 -0700476 getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK);
477 }
478
479 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800480 public View onCreateView(LayoutInflater inflater, ViewGroup container,
481 Bundle savedInstanceState) {
482 View view = inflater.inflate(R.layout.fragment_individual_picker, container, false);
483
Santiago Etchebehere53c63432020-05-07 18:55:35 -0700484 mTileSizePx = SizeCalculator.getIndividualTileSize(getActivity());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800485
486 mImageGrid = (RecyclerView) view.findViewById(R.id.wallpaper_grid);
487 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
488 int gridPaddingPx = getResources().getDimensionPixelSize(R.dimen.grid_padding_desktop);
489 updateImageGridPadding(false /* addExtraBottomSpace */);
490 mImageGrid.setScrollBarSize(gridPaddingPx);
491 }
Chuck Liaoba401232020-03-13 20:11:04 +0800492 mImageGrid.addItemDecoration(new GridPaddingDecoration(
493 getResources().getDimensionPixelSize(R.dimen.grid_padding)));
Wesley.CW Wangdc68fde2020-06-15 19:12:33 +0800494 mImageGrid.setAccessibilityDelegateCompat(
495 new WallpaperPickerRecyclerViewAccessibilityDelegate(
496 mImageGrid, (BottomSheetHost) getParentFragment(), getNumColumns()));
Chuck Liaof6b4b192020-08-07 02:31:32 +0800497 mLoading = view.findViewById(R.id.loading_indicator);
498 updateLoading();
Santiago Etchebehere460fbcb2019-08-20 11:47:30 -0700499 maybeSetUpImageGrid();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800500 setUpBottomSheet();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800501 return view;
502 }
503
504 @Override
505 public void onClickTryAgain(@Destination int unused) {
506 if (mPendingSetIndividualHolder != null) {
507 mPendingSetIndividualHolder.setWallpaper();
508 }
509 }
510
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800511 void updateImageGridPadding(boolean addExtraBottomSpace) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800512 int gridPaddingPx = getResources().getDimensionPixelSize(R.dimen.grid_padding_desktop);
513 int bottomSheetHeightPx = getResources().getDimensionPixelSize(
514 R.dimen.current_wallpaper_bottom_sheet_layout_height);
515 int paddingBottomPx = addExtraBottomSpace ? bottomSheetHeightPx : 0;
516 // Only left and top may be set in order for the GridMarginDecoration to work properly.
517 mImageGrid.setPadding(
518 gridPaddingPx, gridPaddingPx, 0, paddingBottomPx);
519 }
520
Chuck Liaof6b4b192020-08-07 02:31:32 +0800521 private IndividualPickerFragmentHost getIndividualPickerFragmentHost() {
Chuck Liao7e333722021-02-27 02:21:20 +0800522 Fragment parentFragment = getParentFragment();
523 if (parentFragment != null) {
524 return (IndividualPickerFragmentHost) parentFragment;
525 } else {
526 return (IndividualPickerFragmentHost) getActivity();
527 }
Chuck Liaof6b4b192020-08-07 02:31:32 +0800528 }
529
Santiago Etchebehere460fbcb2019-08-20 11:47:30 -0700530 private void maybeSetUpImageGrid() {
Santiago Etchebehere8648bb82019-08-06 17:09:02 -0700531 // Skip if mImageGrid been initialized yet
532 if (mImageGrid == null) {
533 return;
534 }
535 // Skip if category hasn't loaded yet
536 if (mCategory == null) {
537 return;
538 }
539 // Skip if the adapter was already created
540 if (mAdapter != null) {
541 return;
542 }
Santiago Etchebehere460fbcb2019-08-20 11:47:30 -0700543 setUpImageGrid();
544 }
545
546 /**
547 * Create the adapter and assign it to mImageGrid.
548 * Both mImageGrid and mCategory are guaranteed to not be null when this method is called.
549 */
550 void setUpImageGrid() {
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800551 mAdapter = new IndividualAdapter(mWallpapers);
552 mImageGrid.setAdapter(mAdapter);
553 mImageGrid.setLayoutManager(new GridLayoutManager(getActivity(), getNumColumns()));
554 }
555
Jon Miranda16ea1b12017-12-12 14:52:48 -0800556 /**
557 * Enables and populates the "Currently set" wallpaper BottomSheet.
558 */
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800559 void setUpBottomSheet() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800560 mImageGrid.addOnScrollListener(new OnScrollListener() {
561 @Override
562 public void onScrolled(RecyclerView recyclerView, int dx, final int dy) {
563 if (mCurrentWallpaperBottomSheetPresenter == null) {
564 return;
565 }
566
567 if (mCurrentWallpaperBottomSheetExpandedRunnable != null) {
568 mHandler.removeCallbacks(mCurrentWallpaperBottomSheetExpandedRunnable);
569 }
570 mCurrentWallpaperBottomSheetExpandedRunnable = new Runnable() {
571 @Override
572 public void run() {
573 if (dy > 0) {
574 mCurrentWallpaperBottomSheetPresenter.setCurrentWallpapersExpanded(false);
575 } else {
576 mCurrentWallpaperBottomSheetPresenter.setCurrentWallpapersExpanded(true);
577 }
578 }
579 };
580 mHandler.postDelayed(mCurrentWallpaperBottomSheetExpandedRunnable, 100);
581 }
582 });
583 }
584
chihhangchuang3efb6832020-04-17 02:06:25 +0800585 @Override
586 protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
Chuck Liao342f4ab2020-05-26 18:28:09 +0800587 mBottomActionBar = bottomActionBar;
588 if (isRotationEnabled()) {
589 mBottomActionBar.showActionsOnly(ROTATION);
Ching-Sung Li073812b2020-04-07 21:19:21 +0800590 }
Chuck Liao342f4ab2020-05-26 18:28:09 +0800591 mBottomActionBar.setActionClickListener(ROTATION, unused -> {
592 DialogFragment startRotationDialogFragment = new StartRotationDialogFragment();
593 startRotationDialogFragment.setTargetFragment(
594 IndividualPickerFragment.this, UNUSED_REQUEST_CODE);
595 startRotationDialogFragment.show(getFragmentManager(), TAG_START_ROTATION_DIALOG);
596 });
597 mBottomActionBar.setActionClickListener(APPLY, unused -> {
598 mBottomActionBar.disableActions();
599 mWallpaperSetter.requestDestination(getActivity(), getFragmentManager(), this,
600 mSelectedWallpaperInfo instanceof LiveWallpaperInfo);
601 });
602
603 mWallpaperInfoView = (WallpaperInfoView) LayoutInflater.from(getContext())
604 .inflate(R.layout.wallpaper_info_view, /* root= */ null);
605 mBottomActionBar.attachViewToBottomSheetAndBindAction(mWallpaperInfoView, INFORMATION);
606 mBottomActionBar.setActionClickListener(EDIT, unused -> {
607 mWallpaperPersister.setWallpaperInfoInPreview(mSelectedWallpaperInfo);
608 mSelectedWallpaperInfo.showPreview(getActivity(),
609 new PreviewActivity.PreviewActivityIntentFactory(),
610 PREVIEW_WALLPAPER_REQUEST_CODE);
611 });
612 mBottomActionBar.show();
Ching-Sung Li073812b2020-04-07 21:19:21 +0800613 }
614
Jon Miranda16ea1b12017-12-12 14:52:48 -0800615 @Override
616 public void onResume() {
617 super.onResume();
618
Santiago Etchebehere8cad0dd2019-10-17 10:52:39 -0700619 WallpaperPreferences preferences = InjectorProvider.getInjector()
620 .getPreferences(getActivity());
Jon Miranda16ea1b12017-12-12 14:52:48 -0800621 preferences.setLastAppActiveTimestamp(new Date().getTime());
622
623 // Reset Glide memory settings to a "normal" level of usage since it may have been lowered in
624 // PreviewFragment.
625 Glide.get(getActivity()).setMemoryCategory(MemoryCategory.NORMAL);
626
627 // Show the staged 'start rotation' error dialog fragment if there is one that was unable to be
628 // shown earlier when this fragment's hosting activity didn't allow committing fragment
629 // transactions.
630 if (mStagedStartRotationErrorDialogFragment != null) {
631 mStagedStartRotationErrorDialogFragment.show(
632 getFragmentManager(), TAG_START_ROTATION_ERROR_DIALOG);
633 mStagedStartRotationErrorDialogFragment = null;
634 }
635
636 // Show the staged 'load wallpaper' or 'set wallpaper' error dialog fragments if there is one
637 // that was unable to be shown earlier when this fragment's hosting activity didn't allow
638 // committing fragment transactions.
639 if (mStagedSetWallpaperErrorDialogFragment != null) {
640 mStagedSetWallpaperErrorDialogFragment.show(
641 getFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
642 mStagedSetWallpaperErrorDialogFragment = null;
643 }
644
Chuck Liao5a4243b2020-05-20 23:56:39 +0800645 if (shouldShowRotationTile() && mWasUpdateRunnableRun && !mWallpapers.isEmpty()) {
646 // Must be resuming from a previously stopped state, so re-schedule the update of the
647 // daily wallpapers tile thumbnail.
648 mUpdateDailyWallpaperThumbRunnable.run();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800649 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800650 }
651
652 @Override
653 public void onStop() {
654 super.onStop();
655 mHandler.removeCallbacks(mUpdateDailyWallpaperThumbRunnable);
656 }
657
658 @Override
659 public void onDestroy() {
660 super.onDestroy();
661 if (mProgressDialog != null) {
662 mProgressDialog.dismiss();
663 }
664 mWallpaperChangedNotifier.unregisterListener(mWallpaperChangedListener);
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700665 if (mAppStatusListener != null) {
666 mPackageStatusNotifier.removeListener(mAppStatusListener);
667 }
Chuck Liao69630f12020-03-05 19:01:25 +0800668 mWallpaperSetter.cleanUp();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800669 }
670
671 @Override
Chihhang Chuang85f099a2020-06-16 18:04:39 +0800672 public void onStartRotationDialogDismiss(@NonNull DialogInterface dialog) {
chihhangchuang8f9da5f2020-06-17 00:32:18 +0800673 // TODO(b/159310028): Refactor fragment layer to make it able to restore from config change.
674 // This is to handle config change with StartRotationDialog popup, the StartRotationDialog
675 // still holds a reference to the destroyed Fragment and is calling
676 // onStartRotationDialogDismissed on that destroyed Fragment.
677 if (mBottomActionBar != null) {
678 mBottomActionBar.deselectAction(ROTATION);
679 }
Chihhang Chuang85f099a2020-06-16 18:04:39 +0800680 }
681
682 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800683 public void retryStartRotation(@NetworkPreference int networkPreference) {
684 startRotation(networkPreference);
685 }
686
chihhangchuang7feb3752020-04-24 02:48:56 +0800687 @Override
688 public boolean onBackPressed() {
689 if (mSelectedWallpaperInfo != null) {
690 onWallpaperSelected(null, 0);
691 return true;
692 }
693 return false;
694 }
695
Jon Miranda16ea1b12017-12-12 14:52:48 -0800696 public void setCurrentWallpaperBottomSheetPresenter(
697 CurrentWallpaperBottomSheetPresenter presenter) {
698 mCurrentWallpaperBottomSheetPresenter = presenter;
699 }
700
701 public void setWallpapersUiContainer(WallpapersUiContainer uiContainer) {
702 mWallpapersUiContainer = uiContainer;
703 }
704
Chuck Liaob3829fb2020-04-01 00:47:50 +0800705 public void setOnWallpaperSelectedListener(
706 WallpaperSelectedListener wallpaperSelectedListener) {
707 mWallpaperSelectedListener = wallpaperSelectedListener;
708 }
709
710 /**
711 * Resizes the layout's height.
712 */
713 public void resizeLayout(int height) {
714 mImageGrid.getLayoutParams().height = height;
715 mImageGrid.requestLayout();
716 }
717
718 /**
719 * Scrolls to the specific item.
720 *
721 * @param position the position of the item
722 */
723 public void scrollToPosition(int position) {
724 ((GridLayoutManager) mImageGrid.getLayoutManager())
725 .scrollToPositionWithOffset(position, /* offset= */ 0);
726 }
727
Jon Miranda16ea1b12017-12-12 14:52:48 -0800728 /**
729 * Enable a test mode of operation -- in which certain UI features are disabled to allow for
730 * UI tests to run correctly. Works around issue in ProgressDialog currently where the dialog
731 * constantly keeps the UI thread alive and blocks a test forever.
732 *
733 * @param testingMode
734 */
735 void setTestingMode(boolean testingMode) {
736 mTestingMode = testingMode;
737 }
738
Jon Miranda16ea1b12017-12-12 14:52:48 -0800739 @Override
740 public void startRotation(@NetworkPreference final int networkPreference) {
741 if (!isRotationEnabled()) {
742 Log.e(TAG, "Rotation is not enabled for this category " + mCategory.getTitle());
743 return;
744 }
745
746 // ProgressDialog endlessly updates the UI thread, keeping it from going idle which therefore
747 // causes Espresso to hang once the dialog is shown.
748 if (mFormFactor == FormFactorChecker.FORM_FACTOR_MOBILE && !mTestingMode) {
749 int themeResId;
750 if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
751 themeResId = R.style.ProgressDialogThemePreL;
752 } else {
753 themeResId = R.style.LightDialogTheme;
754 }
755 mProgressDialog = new ProgressDialog(getActivity(), themeResId);
756
757 mProgressDialog.setTitle(PROGRESS_DIALOG_NO_TITLE);
758 mProgressDialog.setMessage(
759 getResources().getString(R.string.start_rotation_progress_message));
760 mProgressDialog.setIndeterminate(PROGRESS_DIALOG_INDETERMINATE);
761 mProgressDialog.show();
762 }
763
764 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
765 mAdapter.mPendingSelectedAdapterPosition = SPECIAL_FIXED_TILE_ADAPTER_POSITION;
766 }
767
768 final Context appContext = getActivity().getApplicationContext();
769
770 mWallpaperRotationInitializer.setFirstWallpaperInRotation(
771 appContext,
772 networkPreference,
773 new Listener() {
774 @Override
775 public void onFirstWallpaperInRotationSet() {
776 if (mProgressDialog != null) {
777 mProgressDialog.dismiss();
778 }
779
780 // The fragment may be detached from its containing activity if the user exits the
781 // app before the first wallpaper image in rotation finishes downloading.
782 Activity activity = getActivity();
783
Jon Miranda16ea1b12017-12-12 14:52:48 -0800784
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700785 if (mWallpaperRotationInitializer.startRotation(appContext)) {
786 if (activity != null
787 && mFormFactor == FormFactorChecker.FORM_FACTOR_MOBILE) {
788 try {
789 Toast.makeText(getActivity(),
790 R.string.wallpaper_set_successfully_message,
791 Toast.LENGTH_SHORT).show();
792 } catch (NotFoundException e) {
793 Log.e(TAG, "Could not show toast " + e);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800794 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800795
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700796 activity.setResult(Activity.RESULT_OK);
797 activity.finish();
798 } else if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
799 mAdapter.updateSelectedTile(SPECIAL_FIXED_TILE_ADAPTER_POSITION);
800 }
801 } else { // Failed to start rotation.
802 showStartRotationErrorDialog(networkPreference);
803
804 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
805 DesktopRotationHolder rotationViewHolder =
806 (DesktopRotationHolder)
807 mImageGrid.findViewHolderForAdapterPosition(
808 SPECIAL_FIXED_TILE_ADAPTER_POSITION);
809 rotationViewHolder.setSelectionState(
810 SelectableHolder.SELECTION_STATE_DESELECTED);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800811 }
812 }
813 }
814
815 @Override
816 public void onError() {
817 if (mProgressDialog != null) {
818 mProgressDialog.dismiss();
819 }
820
821 showStartRotationErrorDialog(networkPreference);
822
823 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
824 DesktopRotationHolder rotationViewHolder =
825 (DesktopRotationHolder) mImageGrid.findViewHolderForAdapterPosition(
826 SPECIAL_FIXED_TILE_ADAPTER_POSITION);
827 rotationViewHolder.setSelectionState(SelectableHolder.SELECTION_STATE_DESELECTED);
828 }
829 }
830 });
831 }
832
833 private void showStartRotationErrorDialog(@NetworkPreference int networkPreference) {
Chuck Liaob17d1502020-09-07 21:55:30 +0800834 FragmentTransactionChecker activity = (FragmentTransactionChecker) getActivity();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800835 if (activity != null) {
836 StartRotationErrorDialogFragment startRotationErrorDialogFragment =
837 StartRotationErrorDialogFragment.newInstance(networkPreference);
838 startRotationErrorDialogFragment.setTargetFragment(
839 IndividualPickerFragment.this, UNUSED_REQUEST_CODE);
840
841 if (activity.isSafeToCommitFragmentTransaction()) {
842 startRotationErrorDialogFragment.show(
843 getFragmentManager(), TAG_START_ROTATION_ERROR_DIALOG);
844 } else {
845 mStagedStartRotationErrorDialogFragment = startRotationErrorDialogFragment;
846 }
847 }
848 }
849
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800850 int getNumColumns() {
Ching-Sung Li9df77a32019-07-10 11:45:30 +0800851 Activity activity = getActivity();
Chuck Liaoe2fe0302020-06-29 21:15:35 +0800852 return activity == null ? 1 : SizeCalculator.getNumIndividualColumns(activity);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800853 }
854
855 /**
856 * Returns whether rotation is enabled for this category.
857 */
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800858 boolean isRotationEnabled() {
Samuel Fufa03bc6ac2019-09-19 12:01:50 -0700859 return mWallpaperRotationInitializer != null;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800860 }
861
862 @Override
863 public void onCurrentWallpaperRefreshed() {
864 mCurrentWallpaperBottomSheetPresenter.setCurrentWallpapersExpanded(true);
865 }
866
Chuck Liao69630f12020-03-05 19:01:25 +0800867 @Override
868 public void onSet(int destination) {
869 if (mSelectedWallpaperInfo == null) {
870 Log.e(TAG, "Unable to set wallpaper since the selected wallpaper info is null");
871 return;
872 }
873
“Chuckffd832c2020-03-22 02:15:58 +0800874 mWallpaperPersister.setWallpaperInfoInPreview(mSelectedWallpaperInfo);
Chuck Liao69630f12020-03-05 19:01:25 +0800875 if (mSelectedWallpaperInfo instanceof LiveWallpaperInfo) {
876 mWallpaperSetter.setCurrentWallpaper(getActivity(), mSelectedWallpaperInfo, null,
877 destination, 0, null, mSetWallpaperCallback);
878 } else {
879 mWallpaperSetter.setCurrentWallpaper(
880 getActivity(), mSelectedWallpaperInfo, destination, mSetWallpaperCallback);
881 }
“Chuck7ef99722020-03-22 04:34:03 +0800882 onWallpaperDestinationSet(destination);
Chuck Liao69630f12020-03-05 19:01:25 +0800883 }
884
885 private WallpaperPersister.SetWallpaperCallback mSetWallpaperCallback =
886 new WallpaperPersister.SetWallpaperCallback() {
887 @Override
“Chuckffd832c2020-03-22 02:15:58 +0800888 public void onSuccess(WallpaperInfo wallpaperInfo) {
chihhangchuang210c9602020-06-02 12:38:14 +0800889 mWallpaperPersister.onLiveWallpaperSet();
Chuck Liao6e52fff2020-04-23 16:11:23 +0800890 Toast.makeText(getActivity(), R.string.wallpaper_set_successfully_message,
891 Toast.LENGTH_SHORT).show();
chihhangchuang210c9602020-06-02 12:38:14 +0800892 getActivity().overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
893 getActivity().finish();
Chuck Liao69630f12020-03-05 19:01:25 +0800894 }
895
896 @Override
897 public void onError(@Nullable Throwable throwable) {
898 Log.e(TAG, "Can't apply the wallpaper.");
899 mBottomActionBar.enableActions();
900 }
901 };
902
903 @Override
904 public void onDialogDismissed(boolean withItemSelected) {
905 if (!withItemSelected) {
906 mBottomActionBar.enableActions();
907 }
908 }
909
Jon Miranda16ea1b12017-12-12 14:52:48 -0800910 /**
911 * Shows a "set wallpaper" error dialog with a failure message and button to try again.
912 */
913 private void showSetWallpaperErrorDialog() {
914 SetWallpaperErrorDialogFragment dialogFragment = SetWallpaperErrorDialogFragment.newInstance(
915 R.string.set_wallpaper_error_message, WallpaperPersister.DEST_BOTH);
916 dialogFragment.setTargetFragment(this, UNUSED_REQUEST_CODE);
917
918 if (((BaseActivity) getActivity()).isSafeToCommitFragmentTransaction()) {
919 dialogFragment.show(getFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
920 } else {
921 mStagedSetWallpaperErrorDialogFragment = dialogFragment;
922 }
923 }
924
Ching-Sung Li073812b2020-04-07 21:19:21 +0800925 void updateBottomActions(boolean hasWallpaperSelected) {
chihhangchuang803ea9a2020-04-21 13:03:10 +0800926 if (hasWallpaperSelected) {
Chuck Liao7dc21572020-05-14 18:37:36 +0800927 mBottomActionBar.showActionsOnly(INFORMATION, EDIT, APPLY);
chihhangchuang803ea9a2020-04-21 13:03:10 +0800928 } else {
chihhangchuang08abb582020-04-27 17:20:31 +0800929 mBottomActionBar.showActionsOnly(ROTATION);
chihhangchuang803ea9a2020-04-21 13:03:10 +0800930 }
Chuck Liao69630f12020-03-05 19:01:25 +0800931 }
932
933 private void updateThumbnail(WallpaperInfo selectedWallpaperInfo) {
Chuck Liaof40063f2020-03-03 18:35:24 +0800934 ThumbnailUpdater thumbnailUpdater = (ThumbnailUpdater) getParentFragment();
Chuck Liao69630f12020-03-05 19:01:25 +0800935 if (thumbnailUpdater == null) {
936 return;
937 }
938
939 if (selectedWallpaperInfo != null) {
940 thumbnailUpdater.updateThumbnail(selectedWallpaperInfo);
941 } else {
942 thumbnailUpdater.restoreThumbnails();
Chuck Liaof40063f2020-03-03 18:35:24 +0800943 }
944 }
945
“Chuck7ef99722020-03-22 04:34:03 +0800946 private void onWallpaperDestinationSet(int destination) {
947 WallpaperDestinationCallback wallpaperDestinationCallback =
948 (WallpaperDestinationCallback) getParentFragment();
949 if (wallpaperDestinationCallback == null) {
950 return;
951 }
952
953 wallpaperDestinationCallback.onDestinationSet(destination);
954 }
955
Ching-Sung Li073812b2020-04-07 21:19:21 +0800956 void onWallpaperSelected(@Nullable WallpaperInfo newSelectedWallpaperInfo,
Chuck Liaob3829fb2020-04-01 00:47:50 +0800957 int position) {
chihhangchuang22aa0cc2020-03-25 19:12:42 +0800958 if (mSelectedWallpaperInfo == newSelectedWallpaperInfo) {
“Chuckffd832c2020-03-22 02:15:58 +0800959 return;
960 }
chihhangchuang22aa0cc2020-03-25 19:12:42 +0800961 // Update current wallpaper.
“Chuckffd832c2020-03-22 02:15:58 +0800962 updateActivatedStatus(mSelectedWallpaperInfo == null
963 ? mAppliedWallpaperInfo : mSelectedWallpaperInfo, false);
chihhangchuang22aa0cc2020-03-25 19:12:42 +0800964 // Update new selected wallpaper.
965 updateActivatedStatus(newSelectedWallpaperInfo == null
966 ? mAppliedWallpaperInfo : newSelectedWallpaperInfo, true);
967
968 mSelectedWallpaperInfo = newSelectedWallpaperInfo;
969 updateBottomActions(mSelectedWallpaperInfo != null);
970 updateThumbnail(mSelectedWallpaperInfo);
chihhangchuangde9e8722020-05-02 17:22:13 +0800971 // Populate wallpaper info into view.
chihhangchuang1a29e752020-04-28 18:22:53 +0800972 if (mSelectedWallpaperInfo != null && mWallpaperInfoView != null) {
chihhangchuangc687d912020-05-04 14:33:05 +0800973 WallpaperInfoHelper.loadExploreIntent(
974 getContext(),
975 mSelectedWallpaperInfo,
976 (actionLabel, exploreIntent) ->
977 mWallpaperInfoView.populateWallpaperInfo(
Chuck Liao9991d682021-01-20 17:45:14 +0800978 mSelectedWallpaperInfo,
979 actionLabel,
980 WallpaperInfoHelper.shouldShowExploreButton(
981 getContext(), exploreIntent),
982 v -> onExploreClicked(exploreIntent))
983 );
Chuck Liaob3829fb2020-04-01 00:47:50 +0800984 }
985
986 if (mWallpaperSelectedListener != null) {
987 mWallpaperSelectedListener.onWallpaperSelected(position);
chihhangchuang22aa0cc2020-03-25 19:12:42 +0800988 }
Chuck Liaof40063f2020-03-03 18:35:24 +0800989 }
990
chihhangchuangc687d912020-05-04 14:33:05 +0800991 private void onExploreClicked(Intent exploreIntent) {
992 if (getContext() == null) {
993 return;
994 }
995 Context context = getContext();
996 mUserEventLogger.logActionClicked(mSelectedWallpaperInfo.getCollectionId(context),
997 mSelectedWallpaperInfo.getActionLabelRes(context));
998
999 startActivity(exploreIntent);
1000 }
1001
Chuck Liao6a37a1c2020-03-07 03:39:43 +08001002 private void updateActivatedStatus(WallpaperInfo wallpaperInfo, boolean isActivated) {
“Chuckffd832c2020-03-22 02:15:58 +08001003 if (wallpaperInfo == null) {
1004 return;
1005 }
Chuck Liao6a37a1c2020-03-07 03:39:43 +08001006 int index = mWallpapers.indexOf(wallpaperInfo);
Chuck Liao5a4243b2020-05-20 23:56:39 +08001007 index = (shouldShowRotationTile() || mCategory.supportsCustomPhotos())
Chuck Liao6a37a1c2020-03-07 03:39:43 +08001008 ? index + 1 : index;
1009 ViewHolder holder = mImageGrid.findViewHolderForAdapterPosition(index);
1010 if (holder != null) {
1011 holder.itemView.setActivated(isActivated);
1012 } else {
1013 // Item is not visible, make sure the item is re-bound when it becomes visible.
1014 mAdapter.notifyItemChanged(index);
1015 }
1016 }
1017
“Chuckffd832c2020-03-22 02:15:58 +08001018 private void updateAppliedStatus(WallpaperInfo wallpaperInfo, boolean isApplied) {
1019 if (wallpaperInfo == null) {
1020 return;
1021 }
1022 int index = mWallpapers.indexOf(wallpaperInfo);
Chuck Liao5a4243b2020-05-20 23:56:39 +08001023 index = (shouldShowRotationTile() || mCategory.supportsCustomPhotos())
“Chuckffd832c2020-03-22 02:15:58 +08001024 ? index + 1 : index;
1025 ViewHolder holder = mImageGrid.findViewHolderForAdapterPosition(index);
1026 if (holder != null) {
1027 holder.itemView.findViewById(R.id.check_circle)
1028 .setVisibility(isApplied ? View.VISIBLE : View.GONE);
1029 } else {
1030 // Item is not visible, make sure the item is re-bound when it becomes visible.
1031 mAdapter.notifyItemChanged(index);
1032 }
1033 }
1034
Chuck Liao11f4a762020-04-08 13:24:43 +08001035 private void refreshAppliedWallpaper() {
1036 // Clear the check mark and blue border(if it shows) of the old applied wallpaper.
1037 showCheckMarkAndBorderForAppliedWallpaper(false);
1038
1039 // Update to the new applied wallpaper.
1040 String appliedWallpaperId = getAppliedWallpaperId();
1041 Optional<WallpaperInfo> wallpaperInfoOptional = mWallpapers
1042 .stream()
1043 .filter(wallpaper -> wallpaper.getWallpaperId() != null)
1044 .filter(wallpaper -> wallpaper.getWallpaperId().equals(appliedWallpaperId))
1045 .findFirst();
1046 mAppliedWallpaperInfo = wallpaperInfoOptional.orElse(null);
1047
1048 // Set the check mark and blue border(if user doesn't select) of the new applied wallpaper.
1049 showCheckMarkAndBorderForAppliedWallpaper(true);
1050 }
1051
1052 private String getAppliedWallpaperId() {
1053 WallpaperPreferences prefs =
1054 InjectorProvider.getInjector().getPreferences(getContext());
1055 android.app.WallpaperInfo wallpaperInfo = mWallpaperManager.getWallpaperInfo();
1056 boolean isDestinationBoth =
1057 mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK) < 0;
1058
1059 if (isDestinationBoth || mWallpaperDestination == WallpaperPersister.DEST_HOME_SCREEN) {
1060 return wallpaperInfo != null
1061 ? wallpaperInfo.getServiceName() : prefs.getHomeWallpaperRemoteId();
1062 } else {
1063 return prefs.getLockWallpaperRemoteId();
1064 }
1065 }
1066
1067 private void showCheckMarkAndBorderForAppliedWallpaper(boolean show) {
1068 updateAppliedStatus(mAppliedWallpaperInfo, show);
1069 if (mSelectedWallpaperInfo == null) {
1070 updateActivatedStatus(mAppliedWallpaperInfo, show);
1071 }
1072 }
1073
Chuck Liao5a4243b2020-05-20 23:56:39 +08001074 private boolean shouldShowRotationTile() {
1075 return mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP && isRotationEnabled();
Jon Miranda16ea1b12017-12-12 14:52:48 -08001076 }
1077
1078 /**
1079 * RecyclerView Adapter subclass for the wallpaper tiles in the RecyclerView.
1080 */
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +08001081 class IndividualAdapter extends RecyclerView.Adapter<ViewHolder> {
1082 static final int ITEM_VIEW_TYPE_ROTATION = 1;
1083 static final int ITEM_VIEW_TYPE_INDIVIDUAL_WALLPAPER = 2;
1084 static final int ITEM_VIEW_TYPE_MY_PHOTOS = 3;
Jon Miranda16ea1b12017-12-12 14:52:48 -08001085
1086 private final List<WallpaperInfo> mWallpapers;
1087
1088 private int mPendingSelectedAdapterPosition;
1089 private int mSelectedAdapterPosition;
1090
1091 IndividualAdapter(List<WallpaperInfo> wallpapers) {
1092 mWallpapers = wallpapers;
1093 mPendingSelectedAdapterPosition = -1;
1094 mSelectedAdapterPosition = -1;
1095 }
1096
1097 @Override
1098 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
1099 switch (viewType) {
1100 case ITEM_VIEW_TYPE_ROTATION:
1101 return createRotationHolder(parent);
1102 case ITEM_VIEW_TYPE_INDIVIDUAL_WALLPAPER:
1103 return createIndividualHolder(parent);
1104 case ITEM_VIEW_TYPE_MY_PHOTOS:
1105 return createMyPhotosHolder(parent);
1106 default:
1107 Log.e(TAG, "Unsupported viewType " + viewType + " in IndividualAdapter");
1108 return null;
1109 }
1110 }
1111
1112 @Override
1113 public int getItemViewType(int position) {
Chuck Liao5a4243b2020-05-20 23:56:39 +08001114 if (shouldShowRotationTile() && position == SPECIAL_FIXED_TILE_ADAPTER_POSITION) {
Jon Miranda16ea1b12017-12-12 14:52:48 -08001115 return ITEM_VIEW_TYPE_ROTATION;
1116 }
1117
1118 // A category cannot have both a "start rotation" tile and a "my photos" tile.
1119 if (mCategory.supportsCustomPhotos()
1120 && !isRotationEnabled()
1121 && position == SPECIAL_FIXED_TILE_ADAPTER_POSITION) {
1122 return ITEM_VIEW_TYPE_MY_PHOTOS;
1123 }
1124
1125 return ITEM_VIEW_TYPE_INDIVIDUAL_WALLPAPER;
1126 }
1127
1128 @Override
1129 public void onBindViewHolder(ViewHolder holder, int position) {
1130 int viewType = getItemViewType(position);
1131
1132 switch (viewType) {
1133 case ITEM_VIEW_TYPE_ROTATION:
1134 onBindRotationHolder(holder, position);
1135 break;
1136 case ITEM_VIEW_TYPE_INDIVIDUAL_WALLPAPER:
1137 onBindIndividualHolder(holder, position);
1138 break;
1139 case ITEM_VIEW_TYPE_MY_PHOTOS:
1140 ((MyPhotosViewHolder) holder).bind();
1141 break;
1142 default:
1143 Log.e(TAG, "Unsupported viewType " + viewType + " in IndividualAdapter");
1144 }
1145 }
1146
1147 @Override
1148 public int getItemCount() {
Chuck Liao5a4243b2020-05-20 23:56:39 +08001149 return (shouldShowRotationTile() || mCategory.supportsCustomPhotos())
Jon Miranda16ea1b12017-12-12 14:52:48 -08001150 ? mWallpapers.size() + 1
1151 : mWallpapers.size();
1152 }
1153
1154 private ViewHolder createRotationHolder(ViewGroup parent) {
1155 LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
Chuck Liao5a4243b2020-05-20 23:56:39 +08001156 View view = layoutInflater.inflate(R.layout.grid_item_rotation_desktop, parent, false);
1157 SelectionAnimator selectionAnimator =
1158 new CheckmarkSelectionAnimator(getActivity(), view);
1159 return new DesktopRotationHolder(getActivity(), mTileSizePx.y, view, selectionAnimator,
1160 IndividualPickerFragment.this);
Jon Miranda16ea1b12017-12-12 14:52:48 -08001161 }
1162
1163 private ViewHolder createIndividualHolder(ViewGroup parent) {
1164 LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
1165 View view = layoutInflater.inflate(R.layout.grid_item_image, parent, false);
1166
1167 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
1168 SelectionAnimator selectionAnimator =
1169 new CheckmarkSelectionAnimator(getActivity(), view);
1170 return new SetIndividualHolder(
1171 getActivity(), mTileSizePx.y, view,
1172 selectionAnimator,
1173 new OnSetListener() {
1174 @Override
1175 public void onPendingWallpaperSet(int adapterPosition) {
1176 // Deselect and hide loading indicator for any previously pending tile.
1177 if (mPendingSelectedAdapterPosition != -1) {
1178 ViewHolder oldViewHolder = mImageGrid.findViewHolderForAdapterPosition(
1179 mPendingSelectedAdapterPosition);
1180 if (oldViewHolder instanceof SelectableHolder) {
1181 ((SelectableHolder) oldViewHolder).setSelectionState(
1182 SelectableHolder.SELECTION_STATE_DESELECTED);
1183 }
1184 }
1185
1186 if (mSelectedAdapterPosition != -1) {
1187 ViewHolder oldViewHolder = mImageGrid.findViewHolderForAdapterPosition(
1188 mSelectedAdapterPosition);
1189 if (oldViewHolder instanceof SelectableHolder) {
1190 ((SelectableHolder) oldViewHolder).setSelectionState(
1191 SelectableHolder.SELECTION_STATE_DESELECTED);
1192 }
1193 }
1194
1195 mPendingSelectedAdapterPosition = adapterPosition;
1196 }
1197
1198 @Override
1199 public void onWallpaperSet(int adapterPosition) {
1200 // No-op -- UI handles a new wallpaper being set by reacting to the
1201 // WallpaperChangedNotifier.
1202 }
1203
1204 @Override
1205 public void onWallpaperSetFailed(SetIndividualHolder holder) {
1206 showSetWallpaperErrorDialog();
1207 mPendingSetIndividualHolder = holder;
1208 }
1209 });
1210 } else { // MOBILE
Chuck Liao3d1a51c2020-02-17 18:29:34 +08001211 return new PreviewIndividualHolder(getActivity(), mTileSizePx.y, view);
Jon Miranda16ea1b12017-12-12 14:52:48 -08001212 }
1213 }
1214
1215 private ViewHolder createMyPhotosHolder(ViewGroup parent) {
1216 LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
1217 View view = layoutInflater.inflate(R.layout.grid_item_my_photos, parent, false);
1218
Santiago Etchebeherefab49612019-01-15 12:22:42 -08001219 return new MyPhotosViewHolder(getActivity(),
1220 ((MyPhotosStarterProvider) getActivity()).getMyPhotosStarter(),
1221 mTileSizePx.y, view);
Jon Miranda16ea1b12017-12-12 14:52:48 -08001222 }
1223
1224 /**
1225 * Marks the tile at the given position as selected with a visual indication. Also updates the
1226 * "currently selected" BottomSheet to reflect the newly selected tile.
1227 */
1228 private void updateSelectedTile(int newlySelectedPosition) {
1229 // Prevent multiple spinners from appearing with a user tapping several tiles in rapid
1230 // succession.
1231 if (mPendingSelectedAdapterPosition == mSelectedAdapterPosition) {
1232 return;
1233 }
1234
1235 if (mCurrentWallpaperBottomSheetPresenter != null) {
1236 mCurrentWallpaperBottomSheetPresenter.refreshCurrentWallpapers(
1237 IndividualPickerFragment.this);
1238
1239 if (mCurrentWallpaperBottomSheetExpandedRunnable != null) {
1240 mHandler.removeCallbacks(mCurrentWallpaperBottomSheetExpandedRunnable);
1241 }
1242 mCurrentWallpaperBottomSheetExpandedRunnable = new Runnable() {
1243 @Override
1244 public void run() {
1245 mCurrentWallpaperBottomSheetPresenter.setCurrentWallpapersExpanded(true);
1246 }
1247 };
1248 mHandler.postDelayed(mCurrentWallpaperBottomSheetExpandedRunnable, 100);
1249 }
1250
1251 // User may have switched to another category, thus detaching this fragment, so check here.
1252 // NOTE: We do this check after updating the current wallpaper BottomSheet so that the update
1253 // still occurs in the UI after the user selects that other category.
1254 if (getActivity() == null) {
1255 return;
1256 }
1257
1258 // Update the newly selected wallpaper ViewHolder and the old one so that if
1259 // selection UI state applies (desktop UI), it is updated.
1260 if (mSelectedAdapterPosition >= 0) {
1261 ViewHolder oldViewHolder = mImageGrid.findViewHolderForAdapterPosition(
1262 mSelectedAdapterPosition);
1263 if (oldViewHolder instanceof SelectableHolder) {
1264 ((SelectableHolder) oldViewHolder).setSelectionState(
1265 SelectableHolder.SELECTION_STATE_DESELECTED);
1266 }
1267 }
1268
1269 // Animate selection of newly selected tile.
1270 ViewHolder newViewHolder = mImageGrid
1271 .findViewHolderForAdapterPosition(newlySelectedPosition);
1272 if (newViewHolder instanceof SelectableHolder) {
1273 ((SelectableHolder) newViewHolder).setSelectionState(
1274 SelectableHolder.SELECTION_STATE_SELECTED);
1275 }
1276
1277 mSelectedAdapterPosition = newlySelectedPosition;
1278
1279 // If the tile was in the last row of the grid, add space below it so the user can scroll down
1280 // and up to see the BottomSheet without it fully overlapping the newly selected tile.
1281 int spanCount = ((GridLayoutManager) mImageGrid.getLayoutManager()).getSpanCount();
1282 int numRows = (int) Math.ceil((float) getItemCount() / spanCount);
1283 int rowOfNewlySelectedTile = newlySelectedPosition / spanCount;
1284 boolean isInLastRow = rowOfNewlySelectedTile == numRows - 1;
1285
1286 updateImageGridPadding(isInLastRow /* addExtraBottomSpace */);
1287 }
1288
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +08001289 void onBindRotationHolder(ViewHolder holder, int position) {
Jon Miranda16ea1b12017-12-12 14:52:48 -08001290 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
1291 String collectionId = mCategory.getCollectionId();
1292 ((DesktopRotationHolder) holder).bind(collectionId);
1293
1294 if (mWallpaperPreferences.getWallpaperPresentationMode()
1295 == WallpaperPreferences.PRESENTATION_MODE_ROTATING
1296 && collectionId.equals(mWallpaperPreferences.getHomeWallpaperCollectionId())) {
1297 mSelectedAdapterPosition = position;
1298 }
1299
1300 if (!mWasUpdateRunnableRun && !mWallpapers.isEmpty()) {
1301 updateDesktopDailyRotationThumbnail((DesktopRotationHolder) holder);
1302 mWasUpdateRunnableRun = true;
1303 }
1304 }
1305 }
1306
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +08001307 void onBindIndividualHolder(ViewHolder holder, int position) {
Chuck Liao5a4243b2020-05-20 23:56:39 +08001308 int wallpaperIndex = (shouldShowRotationTile() || mCategory.supportsCustomPhotos())
Jon Miranda16ea1b12017-12-12 14:52:48 -08001309 ? position - 1 : position;
1310 WallpaperInfo wallpaper = mWallpapers.get(wallpaperIndex);
1311 ((IndividualHolder) holder).bindWallpaper(wallpaper);
“Chuck7ef99722020-03-22 04:34:03 +08001312 String appliedWallpaperId = getAppliedWallpaperId();
“Chuckffd832c2020-03-22 02:15:58 +08001313 boolean isWallpaperApplied = wallpaper.getWallpaperId().equals(appliedWallpaperId);
1314 boolean isWallpaperSelected = wallpaper.equals(mSelectedWallpaperInfo);
1315 boolean hasUserSelectedWallpaper = mSelectedWallpaperInfo != null;
Jon Miranda16ea1b12017-12-12 14:52:48 -08001316
“Chuckffd832c2020-03-22 02:15:58 +08001317 if (isWallpaperApplied) {
Jon Miranda16ea1b12017-12-12 14:52:48 -08001318 mSelectedAdapterPosition = position;
“Chuckffd832c2020-03-22 02:15:58 +08001319 mAppliedWallpaperInfo = wallpaper;
Jon Miranda16ea1b12017-12-12 14:52:48 -08001320 }
Chuck Liaof40063f2020-03-03 18:35:24 +08001321
Chuck Liao342f4ab2020-05-26 18:28:09 +08001322 holder.itemView.setActivated(
1323 (isWallpaperApplied && !hasUserSelectedWallpaper) || isWallpaperSelected);
1324 holder.itemView.findViewById(R.id.check_circle).setVisibility(
1325 isWallpaperApplied ? View.VISIBLE : View.GONE);
Jon Miranda16ea1b12017-12-12 14:52:48 -08001326 }
1327 }
Chuck Liaoba401232020-03-13 20:11:04 +08001328
1329 private class GridPaddingDecoration extends RecyclerView.ItemDecoration {
1330
1331 private int mPadding;
1332
1333 GridPaddingDecoration(int padding) {
1334 mPadding = padding;
1335 }
1336
1337 @Override
1338 public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
1339 RecyclerView.State state) {
1340 int position = parent.getChildAdapterPosition(view);
1341 if (position >= 0) {
1342 outRect.left = mPadding;
1343 outRect.right = mPadding;
1344 }
1345 }
1346 }
Jon Miranda16ea1b12017-12-12 14:52:48 -08001347}