| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.wallpaper.picker; |
| |
| import android.app.Activity; |
| import android.app.ProgressDialog; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.pm.PackageManager; |
| import android.graphics.Point; |
| import android.graphics.PorterDuff.Mode; |
| import android.net.Uri; |
| import android.os.Build.VERSION; |
| import android.os.Build.VERSION_CODES; |
| import android.os.Bundle; |
| import android.provider.Settings; |
| import android.util.DisplayMetrics; |
| import android.util.Log; |
| import android.view.Display; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.View.OnClickListener; |
| import android.view.ViewGroup; |
| import android.widget.Button; |
| import android.widget.FrameLayout; |
| import android.widget.ImageButton; |
| import android.widget.ImageView; |
| import android.widget.TextView; |
| |
| import androidx.annotation.NonNull; |
| import androidx.annotation.Nullable; |
| import androidx.appcompat.app.AlertDialog; |
| import androidx.cardview.widget.CardView; |
| import androidx.recyclerview.widget.RecyclerView; |
| import androidx.viewpager.widget.PagerAdapter; |
| |
| import com.android.wallpaper.R; |
| import com.android.wallpaper.config.Flags; |
| import com.android.wallpaper.model.Category; |
| import com.android.wallpaper.model.WallpaperInfo; |
| import com.android.wallpaper.module.CurrentWallpaperInfoFactory; |
| import com.android.wallpaper.module.CurrentWallpaperInfoFactory.WallpaperInfoCallback; |
| import com.android.wallpaper.module.ExploreIntentChecker; |
| import com.android.wallpaper.module.InjectorProvider; |
| import com.android.wallpaper.module.LockWallpaperStatusChecker; |
| import com.android.wallpaper.module.UserEventLogger; |
| import com.android.wallpaper.module.WallpaperPreferences; |
| import com.android.wallpaper.module.WallpaperPreferences.PresentationMode; |
| import com.android.wallpaper.module.WallpaperRotationRefresher; |
| import com.android.wallpaper.module.WallpaperRotationRefresher.Listener; |
| import com.android.wallpaper.picker.CategorySelectorFragment.CategorySelectorFragmentHost; |
| import com.android.wallpaper.picker.MyPhotosStarter.MyPhotosStarterProvider; |
| import com.android.wallpaper.picker.MyPhotosStarter.PermissionChangedListener; |
| import com.android.wallpaper.util.DisplayMetricsRetriever; |
| import com.android.wallpaper.util.ScreenSizeCalculator; |
| import com.android.wallpaper.widget.PreviewPager; |
| |
| import com.bumptech.glide.Glide; |
| import com.bumptech.glide.MemoryCategory; |
| import com.google.android.material.bottomsheet.BottomSheetBehavior; |
| |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.List; |
| |
| /** |
| * Displays the Main UI for picking a category of wallpapers to choose from. |
| */ |
| public class CategoryFragment extends ToolbarFragment implements CategorySelectorFragmentHost { |
| |
| /** |
| * Interface to be implemented by an Activity hosting a {@link CategoryFragment} |
| */ |
| public interface CategoryFragmentHost extends MyPhotosStarterProvider { |
| |
| void requestExternalStoragePermission(PermissionChangedListener listener); |
| |
| boolean isReadExternalStoragePermissionGranted(); |
| |
| void showViewOnlyPreview(WallpaperInfo wallpaperInfo); |
| } |
| |
| public static CategoryFragment newInstance(CharSequence title) { |
| CategoryFragment fragment = new CategoryFragment(); |
| fragment.setArguments(ToolbarFragment.createArguments(title)); |
| return fragment; |
| } |
| |
| private static final String TAG = "CategoryFragment"; |
| |
| // The number of ViewHolders that don't pertain to category tiles. |
| // Currently 2: one for the metadata section and one for the "Select wallpaper" header. |
| private static final int NUM_NON_CATEGORY_VIEW_HOLDERS = 0; |
| |
| private static final int SETTINGS_APP_INFO_REQUEST_CODE = 1; |
| |
| private static final String PERMISSION_READ_WALLPAPER_INTERNAL = |
| "android.permission.READ_WALLPAPER_INTERNAL"; |
| |
| private ProgressDialog mRefreshWallpaperProgressDialog; |
| private boolean mTestingMode; |
| private ImageView mHomePreview; |
| private ImageView mLockscreenPreview; |
| private PreviewPager mPreviewPager; |
| private List<View> mWallPaperPreviews; |
| private CategorySelectorFragment mCategorySelectorFragment; |
| |
| public CategoryFragment() { |
| mCategorySelectorFragment = new CategorySelectorFragment(); |
| } |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| View view = inflater.inflate( |
| ADD_SCALABLE_HEADER |
| ? R.layout.fragment_category_scalable_picker |
| : R.layout.fragment_category_picker, container, /* attachToRoot= */ false); |
| |
| mWallPaperPreviews = new ArrayList<>(); |
| CardView homePreviewCard = (CardView) inflater.inflate( |
| R.layout.wallpaper_preview_card, null); |
| mHomePreview = homePreviewCard.findViewById(R.id.wallpaper_preview_image); |
| mWallPaperPreviews.add(homePreviewCard); |
| |
| if (LockWallpaperStatusChecker.isLockWallpaperSet(getContext())) { |
| CardView lockscreenPreviewCard = (CardView) inflater.inflate( |
| R.layout.wallpaper_preview_card, null); |
| mLockscreenPreview = lockscreenPreviewCard.findViewById(R.id.wallpaper_preview_image); |
| mWallPaperPreviews.add(lockscreenPreviewCard); |
| } |
| |
| mPreviewPager = view.findViewById(R.id.wallpaper_preview_pager); |
| mPreviewPager.setAdapter(new PreviewPagerAdapter(mWallPaperPreviews)); |
| setupCurrentWallpaperPreview(view); |
| |
| view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { |
| @Override |
| public void onLayoutChange(View view, int left, int top, int right, int bottom, |
| int oldLeft, int oldTop, int oldRight, int oldBottom) { |
| View toolBar = view.findViewById(R.id.toolbar); |
| View fragmentContainer = view.findViewById(R.id.category_fragment_container); |
| int minimumHeight = view.getHeight() |
| - toolBar.getHeight() |
| - getResources().getDimensionPixelOffset(R.dimen.preview_pager_height); |
| BottomSheetBehavior.from(fragmentContainer).setPeekHeight(minimumHeight); |
| fragmentContainer.setMinimumHeight(minimumHeight); |
| fragmentContainer.getLayoutParams().height = view.getHeight() - toolBar.getHeight(); |
| view.removeOnLayoutChangeListener(this); |
| } |
| }); |
| |
| setUpToolbar(view); |
| |
| getChildFragmentManager() |
| .beginTransaction() |
| .replace(R.id.category_fragment_container, mCategorySelectorFragment) |
| .commitNow(); |
| return view; |
| } |
| |
| @Override |
| public CharSequence getDefaultTitle() { |
| return getContext().getString(R.string.app_name); |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| |
| WallpaperPreferences preferences = InjectorProvider.getInjector().getPreferences(getActivity()); |
| preferences.setLastAppActiveTimestamp(new Date().getTime()); |
| |
| // Reset Glide memory settings to a "normal" level of usage since it may have been lowered in |
| // PreviewFragment. |
| Glide.get(getActivity()).setMemoryCategory(MemoryCategory.NORMAL); |
| |
| // The wallpaper may have been set while this fragment was paused, so force refresh the current |
| // wallpapers and presentation mode. |
| refreshCurrentWallpapers(/* MetadataHolder= */ null, /* forceRefresh= */ true); |
| } |
| |
| @Override |
| public void onDestroy() { |
| super.onDestroy(); |
| if (mRefreshWallpaperProgressDialog != null) { |
| mRefreshWallpaperProgressDialog.dismiss(); |
| } |
| } |
| |
| @Override |
| public void onActivityResult(int requestCode, int resultCode, Intent data) { |
| if (requestCode == SETTINGS_APP_INFO_REQUEST_CODE) { |
| mCategorySelectorFragment.notifyDataSetChanged(); |
| } |
| } |
| |
| @Override |
| public void requestCustomPhotoPicker(PermissionChangedListener listener) { |
| getFragmentHost().getMyPhotosStarter().requestCustomPhotoPicker(listener); |
| } |
| |
| @Override |
| public void show(String collectionId) { |
| getChildFragmentManager() |
| .beginTransaction() |
| .replace(R.id.category_fragment_container, |
| InjectorProvider.getInjector().getIndividualPickerFragment(collectionId)) |
| .addToBackStack(null) |
| .commit(); |
| getChildFragmentManager().executePendingTransactions(); |
| } |
| |
| /** |
| * Pops the child fragment from the stack if {@link CategoryFragment} is visible to the users. |
| * |
| * @return {@code true} if the child fragment is popped, {@code false} otherwise. |
| */ |
| public boolean popChildFragment() { |
| return isVisible() && getChildFragmentManager().popBackStackImmediate(); |
| } |
| |
| /** |
| * Inserts the given category into the categories list in priority order. |
| */ |
| void addCategory(Category category, boolean loading) { |
| mCategorySelectorFragment.addCategory(category, loading); |
| } |
| |
| void removeCategory(Category category) { |
| mCategorySelectorFragment.removeCategory(category); |
| } |
| |
| void updateCategory(Category category) { |
| mCategorySelectorFragment.updateCategory(category); |
| } |
| |
| void clearCategories() { |
| mCategorySelectorFragment.clearCategories(); |
| } |
| |
| /** |
| * Notifies the CategoryFragment that no further categories are expected so it may hide |
| * the loading indicator. |
| */ |
| void doneFetchingCategories() { |
| mCategorySelectorFragment.doneFetchingCategories(); |
| } |
| |
| /** |
| * Enable a test mode of operation -- in which certain UI features are disabled to allow for |
| * UI tests to run correctly. Works around issue in ProgressDialog currently where the dialog |
| * constantly keeps the UI thread alive and blocks a test forever. |
| */ |
| void setTestingMode(boolean testingMode) { |
| mTestingMode = testingMode; |
| } |
| |
| private boolean canShowCurrentWallpaper() { |
| Activity activity = getActivity(); |
| CategoryFragmentHost host = getFragmentHost(); |
| PackageManager packageManager = activity.getPackageManager(); |
| String packageName = activity.getPackageName(); |
| |
| boolean hasReadWallpaperInternal = packageManager.checkPermission( |
| PERMISSION_READ_WALLPAPER_INTERNAL, packageName) == PackageManager.PERMISSION_GRANTED; |
| return hasReadWallpaperInternal || host.isReadExternalStoragePermissionGranted(); |
| } |
| |
| private void showCurrentWallpaper(View rootView, boolean show) { |
| rootView.findViewById(R.id.wallpaper_preview_pager) |
| .setVisibility(show ? View.VISIBLE : View.GONE); |
| rootView.findViewById(R.id.permission_needed) |
| .setVisibility(show ? View.GONE : View.VISIBLE); |
| } |
| |
| private void setupCurrentWallpaperPreview(View rootView) { |
| if (canShowCurrentWallpaper()) { |
| showCurrentWallpaper(rootView, true); |
| } else { |
| showCurrentWallpaper(rootView, false); |
| |
| Button mAllowAccessButton = rootView |
| .findViewById(R.id.permission_needed_allow_access_button); |
| mAllowAccessButton.setOnClickListener(view -> |
| getFragmentHost().requestExternalStoragePermission( |
| new PermissionChangedListener() { |
| |
| @Override |
| public void onPermissionsGranted() { |
| showCurrentWallpaper(rootView, true); |
| mCategorySelectorFragment.notifyDataSetChanged(); |
| } |
| |
| @Override |
| public void onPermissionsDenied(boolean dontAskAgain) { |
| if (!dontAskAgain) { |
| return; |
| } |
| showPermissionNeededDialog(); |
| } |
| }) |
| ); |
| |
| // Replace explanation text with text containing the Wallpapers app name which replaces |
| // the placeholder. |
| String appName = getString(R.string.app_name); |
| String explanation = getString(R.string.permission_needed_explanation, appName); |
| TextView explanationView = rootView.findViewById(R.id.permission_needed_explanation); |
| explanationView.setText(explanation); |
| } |
| } |
| |
| private void showPermissionNeededDialog() { |
| String permissionNeededMessage = getString( |
| R.string.permission_needed_explanation_go_to_settings); |
| AlertDialog dialog = new AlertDialog.Builder(getActivity(), R.style.LightDialogTheme) |
| .setMessage(permissionNeededMessage) |
| .setPositiveButton(android.R.string.ok, /* onClickListener= */ null) |
| .setNegativeButton( |
| R.string.settings_button_label, |
| (dialogInterface, i) -> { |
| Intent appInfoIntent = new Intent(); |
| appInfoIntent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); |
| Uri uri = Uri.fromParts("package", |
| getActivity().getPackageName(), /* fragment= */ null); |
| appInfoIntent.setData(uri); |
| startActivityForResult(appInfoIntent, SETTINGS_APP_INFO_REQUEST_CODE); |
| }) |
| .create(); |
| dialog.show(); |
| } |
| |
| private CategoryFragmentHost getFragmentHost() { |
| return (CategoryFragmentHost) getActivity(); |
| } |
| |
| /** |
| * Obtains the {@link WallpaperInfo} object(s) representing the wallpaper(s) currently set to the |
| * device from the {@link CurrentWallpaperInfoFactory} and binds them to the provided |
| * {@link MetadataHolder}. |
| */ |
| private void refreshCurrentWallpapers(@Nullable final MetadataHolder holder, |
| boolean forceRefresh) { |
| CurrentWallpaperInfoFactory factory = InjectorProvider.getInjector() |
| .getCurrentWallpaperFactory(getActivity().getApplicationContext()); |
| |
| factory.createCurrentWallpaperInfos(new WallpaperInfoCallback() { |
| @Override |
| public void onWallpaperInfoCreated( |
| final WallpaperInfo homeWallpaper, |
| @Nullable final WallpaperInfo lockWallpaper, |
| @PresentationMode final int presentationMode) { |
| |
| // Update the metadata displayed on screen. Do this in a Handler so it is scheduled at the |
| // end of the message queue. This is necessary to ensure we do not remove or add data from |
| // the adapter while the layout is being computed. RecyclerView documentation therefore |
| // recommends performing such changes in a Handler. |
| new android.os.Handler().post(new Runnable() { |
| @Override |
| public void run() { |
| // A config change may have destroyed the activity since the refresh started, so check |
| // for that. |
| if (getActivity() == null) { |
| return; |
| } |
| |
| UserEventLogger eventLogger = |
| InjectorProvider.getInjector().getUserEventLogger(getActivity()); |
| homeWallpaper.getThumbAsset(getActivity().getApplicationContext()) |
| .loadDrawable(getActivity(), |
| mHomePreview, |
| getResources().getColor(R.color.secondary_color)); |
| mHomePreview.setOnClickListener(view -> { |
| getFragmentHost().showViewOnlyPreview(homeWallpaper); |
| eventLogger.logCurrentWallpaperPreviewed(); |
| }); |
| if (lockWallpaper != null) { |
| lockWallpaper.getThumbAsset(getActivity().getApplicationContext()) |
| .loadDrawable(getActivity(), |
| mLockscreenPreview, |
| getResources().getColor(R.color.secondary_color)); |
| mLockscreenPreview.setOnClickListener(view -> { |
| getFragmentHost().showViewOnlyPreview(lockWallpaper); |
| eventLogger.logCurrentWallpaperPreviewed(); |
| }); |
| } |
| |
| // The MetadataHolder may be null if the RecyclerView has not yet created the view |
| // holder. |
| if (holder != null) { |
| holder.bindWallpapers(homeWallpaper, lockWallpaper, presentationMode); |
| } |
| } |
| }); |
| } |
| }, forceRefresh); |
| } |
| |
| /** |
| * Returns the width to use for the home screen wallpaper in the "single metadata" configuration. |
| */ |
| private int getSingleWallpaperImageWidth() { |
| Point screenSize = ScreenSizeCalculator.getInstance() |
| .getScreenSize(getActivity().getWindowManager().getDefaultDisplay()); |
| |
| int height = getResources().getDimensionPixelSize(R.dimen.single_metadata_card_layout_height); |
| return height * screenSize.x / screenSize.y; |
| } |
| |
| /** |
| * Refreshes the current wallpaper in a daily wallpaper rotation. |
| */ |
| private void refreshDailyWallpaper() { |
| // ProgressDialog endlessly updates the UI thread, keeping it from going idle which therefore |
| // causes Espresso to hang once the dialog is shown. |
| if (!mTestingMode) { |
| int themeResId; |
| if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) { |
| themeResId = R.style.ProgressDialogThemePreL; |
| } else { |
| themeResId = R.style.LightDialogTheme; |
| } |
| mRefreshWallpaperProgressDialog = new ProgressDialog(getActivity(), themeResId); |
| mRefreshWallpaperProgressDialog.setTitle(null); |
| mRefreshWallpaperProgressDialog.setMessage( |
| getResources().getString(R.string.refreshing_daily_wallpaper_dialog_message)); |
| mRefreshWallpaperProgressDialog.setIndeterminate(true); |
| mRefreshWallpaperProgressDialog.setCancelable(false); |
| mRefreshWallpaperProgressDialog.show(); |
| } |
| |
| WallpaperRotationRefresher wallpaperRotationRefresher = |
| InjectorProvider.getInjector().getWallpaperRotationRefresher(); |
| wallpaperRotationRefresher.refreshWallpaper(getContext(), new Listener() { |
| @Override |
| public void onRefreshed() { |
| // If the fragment is detached from the activity there's nothing to do here and the UI will |
| // update when the fragment is resumed. |
| if (getActivity() == null) { |
| return; |
| } |
| |
| if (mRefreshWallpaperProgressDialog != null) { |
| mRefreshWallpaperProgressDialog.dismiss(); |
| } |
| } |
| |
| @Override |
| public void onError() { |
| if (getActivity() == null) { |
| return; |
| } |
| |
| if (mRefreshWallpaperProgressDialog != null) { |
| mRefreshWallpaperProgressDialog.dismiss(); |
| } |
| |
| AlertDialog errorDialog = new AlertDialog.Builder(getActivity(), R.style.LightDialogTheme) |
| .setMessage(R.string.refresh_daily_wallpaper_failed_message) |
| .setPositiveButton(android.R.string.ok, null /* onClickListener */) |
| .create(); |
| errorDialog.show(); |
| } |
| }); |
| } |
| |
| /** |
| * Returns the width to use for the home and lock screen wallpapers in the "both metadata" |
| * configuration. |
| */ |
| private int getBothWallpaperImageWidth() { |
| DisplayMetrics metrics = DisplayMetricsRetriever.getInstance().getDisplayMetrics(getResources(), |
| getActivity().getWindowManager().getDefaultDisplay()); |
| |
| // In the "both metadata" configuration, wallpaper images minus the gutters account for the full |
| // width of the device's screen. |
| return metrics.widthPixels - (3 * getResources().getDimensionPixelSize(R.dimen.grid_padding)); |
| } |
| |
| private interface MetadataHolder { |
| /** |
| * Binds {@link WallpaperInfo} objects representing the currently-set wallpapers to the |
| * ViewHolder layout. |
| */ |
| void bindWallpapers(WallpaperInfo homeWallpaper, WallpaperInfo lockWallpaper, |
| @PresentationMode int presentationMode); |
| } |
| |
| private static class SelectWallpaperHeaderHolder extends RecyclerView.ViewHolder { |
| public SelectWallpaperHeaderHolder(View headerView) { |
| super(headerView); |
| } |
| } |
| |
| /** |
| * ViewHolder subclass for a metadata "card" at the beginning of the RecyclerView. |
| */ |
| private class SingleWallpaperMetadataHolder extends RecyclerView.ViewHolder |
| implements MetadataHolder { |
| private WallpaperInfo mWallpaperInfo; |
| private ImageView mWallpaperImage; |
| private TextView mWallpaperPresentationModeSubtitle; |
| private TextView mWallpaperTitle; |
| private TextView mWallpaperSubtitle; |
| private TextView mWallpaperSubtitle2; |
| private ImageButton mWallpaperExploreButtonNoText; |
| private ImageButton mSkipWallpaperButton; |
| |
| public SingleWallpaperMetadataHolder(View metadataView) { |
| super(metadataView); |
| |
| mWallpaperImage = metadataView.findViewById(R.id.wallpaper_image); |
| mWallpaperImage.getLayoutParams().width = getSingleWallpaperImageWidth(); |
| |
| mWallpaperPresentationModeSubtitle = |
| metadataView.findViewById(R.id.wallpaper_presentation_mode_subtitle); |
| mWallpaperTitle = metadataView.findViewById(R.id.wallpaper_title); |
| mWallpaperSubtitle = metadataView.findViewById(R.id.wallpaper_subtitle); |
| mWallpaperSubtitle2 = metadataView.findViewById(R.id.wallpaper_subtitle2); |
| |
| mWallpaperExploreButtonNoText = |
| metadataView.findViewById(R.id.wallpaper_explore_button_notext); |
| |
| mSkipWallpaperButton = metadataView.findViewById(R.id.skip_wallpaper_button); |
| } |
| |
| /** |
| * Binds home screen wallpaper to the ViewHolder layout. |
| */ |
| @Override |
| public void bindWallpapers(WallpaperInfo homeWallpaper, WallpaperInfo lockWallpaper, |
| @PresentationMode int presentationMode) { |
| mWallpaperInfo = homeWallpaper; |
| |
| bindWallpaperAsset(); |
| bindWallpaperText(presentationMode); |
| bindWallpaperActionButtons(presentationMode); |
| } |
| |
| private void bindWallpaperAsset() { |
| final UserEventLogger eventLogger = |
| InjectorProvider.getInjector().getUserEventLogger(getActivity()); |
| |
| mWallpaperInfo.getThumbAsset(getActivity().getApplicationContext()).loadDrawable( |
| getActivity(), mWallpaperImage, getResources().getColor(R.color.secondary_color)); |
| |
| mWallpaperImage.setOnClickListener(new OnClickListener() { |
| @Override |
| public void onClick(View v) { |
| getFragmentHost().showViewOnlyPreview(mWallpaperInfo); |
| eventLogger.logCurrentWallpaperPreviewed(); |
| } |
| }); |
| } |
| |
| private void bindWallpaperText(@PresentationMode int presentationMode) { |
| Context appContext = getActivity().getApplicationContext(); |
| |
| mWallpaperPresentationModeSubtitle.setText( |
| AttributionFormatter.getHumanReadableWallpaperPresentationMode( |
| appContext, presentationMode)); |
| |
| List<String> attributions = mWallpaperInfo.getAttributions(appContext); |
| if (!attributions.isEmpty()) { |
| mWallpaperTitle.setText(attributions.get(0)); |
| } |
| if (attributions.size() > 1) { |
| mWallpaperSubtitle.setText(attributions.get(1)); |
| } else { |
| mWallpaperSubtitle.setVisibility(View.INVISIBLE); |
| } |
| if (attributions.size() > 2) { |
| mWallpaperSubtitle2.setText(attributions.get(2)); |
| } else { |
| mWallpaperSubtitle2.setVisibility(View.INVISIBLE); |
| } |
| } |
| |
| private void bindWallpaperActionButtons(@PresentationMode int presentationMode) { |
| final Context appContext = getActivity().getApplicationContext(); |
| |
| final String actionUrl = mWallpaperInfo.getActionUrl(appContext); |
| if (actionUrl != null && !actionUrl.isEmpty()) { |
| |
| Uri exploreUri = Uri.parse(actionUrl); |
| |
| ExploreIntentChecker intentChecker = |
| InjectorProvider.getInjector().getExploreIntentChecker(appContext); |
| intentChecker.fetchValidActionViewIntent(exploreUri, (@Nullable Intent exploreIntent) -> { |
| if (getActivity() == null) { |
| return; |
| } |
| |
| updateExploreSectionVisibility(presentationMode, exploreIntent); |
| }); |
| } else { |
| updateExploreSectionVisibility(presentationMode, null /* exploreIntent */); |
| } |
| } |
| |
| /** |
| * Shows or hides appropriate elements in the "Explore section" (containing the Explore button |
| * and the Next Wallpaper button) depending on the current wallpaper. |
| * |
| * @param presentationMode The presentation mode of the current wallpaper. |
| * @param exploreIntent An optional explore intent for the current wallpaper. |
| */ |
| private void updateExploreSectionVisibility( |
| @PresentationMode int presentationMode, @Nullable Intent exploreIntent) { |
| |
| final Context appContext = getActivity().getApplicationContext(); |
| final UserEventLogger eventLogger = |
| InjectorProvider.getInjector().getUserEventLogger(appContext); |
| |
| boolean showSkipWallpaperButton = Flags.skipDailyWallpaperButtonEnabled |
| && presentationMode == WallpaperPreferences.PRESENTATION_MODE_ROTATING; |
| |
| if (exploreIntent != null) { |
| mWallpaperExploreButtonNoText.setImageDrawable(getContext().getDrawable( |
| mWallpaperInfo.getActionIconRes(appContext))); |
| mWallpaperExploreButtonNoText.setContentDescription( |
| getString(mWallpaperInfo.getActionLabelRes(appContext))); |
| mWallpaperExploreButtonNoText.setColorFilter( |
| getResources().getColor(R.color.currently_set_explore_button_color, |
| getContext().getTheme()), |
| Mode.SRC_IN); |
| mWallpaperExploreButtonNoText.setVisibility(View.VISIBLE); |
| mWallpaperExploreButtonNoText.setOnClickListener((View view) -> { |
| eventLogger.logActionClicked(mWallpaperInfo.getCollectionId(appContext), |
| mWallpaperInfo.getActionLabelRes(appContext)); |
| startActivity(exploreIntent); |
| }); |
| } |
| |
| if (showSkipWallpaperButton) { |
| mSkipWallpaperButton.setVisibility(View.VISIBLE); |
| mSkipWallpaperButton.setOnClickListener((View view) -> refreshDailyWallpaper()); |
| } |
| } |
| } |
| |
| /** |
| * ViewHolder subclass for a metadata "card" at the beginning of the RecyclerView that shows |
| * both home screen and lock screen wallpapers. |
| */ |
| private class TwoWallpapersMetadataHolder extends RecyclerView.ViewHolder |
| implements MetadataHolder { |
| private WallpaperInfo mHomeWallpaperInfo; |
| private ImageView mHomeWallpaperImage; |
| private TextView mHomeWallpaperPresentationMode; |
| private TextView mHomeWallpaperTitle; |
| private TextView mHomeWallpaperSubtitle1; |
| private TextView mHomeWallpaperSubtitle2; |
| |
| private ImageButton mHomeWallpaperExploreButton; |
| private ImageButton mSkipWallpaperButton; |
| private ViewGroup mHomeWallpaperPresentationSection; |
| |
| private WallpaperInfo mLockWallpaperInfo; |
| private ImageView mLockWallpaperImage; |
| private TextView mLockWallpaperTitle; |
| private TextView mLockWallpaperSubtitle1; |
| private TextView mLockWallpaperSubtitle2; |
| |
| private ImageButton mLockWallpaperExploreButton; |
| |
| public TwoWallpapersMetadataHolder(View metadataView) { |
| super(metadataView); |
| |
| // Set the min width of the metadata panel to be the screen width minus space for the |
| // 2 gutters on the sides. This ensures the RecyclerView's GridLayoutManager gives it |
| // a wide-enough initial width to fill up the width of the grid prior to the view being |
| // fully populated. |
| final Display display = getActivity().getWindowManager().getDefaultDisplay(); |
| Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display); |
| metadataView.setMinimumWidth( |
| screenSize.x - 2 * getResources().getDimensionPixelSize(R.dimen.grid_padding)); |
| |
| int bothWallpaperImageWidth = getBothWallpaperImageWidth(); |
| |
| FrameLayout homeWallpaperSection = metadataView.findViewById( |
| R.id.home_wallpaper_section); |
| homeWallpaperSection.setMinimumWidth(bothWallpaperImageWidth); |
| mHomeWallpaperImage = metadataView.findViewById(R.id.home_wallpaper_image); |
| |
| mHomeWallpaperPresentationMode = |
| metadataView.findViewById(R.id.home_wallpaper_presentation_mode); |
| mHomeWallpaperTitle = metadataView.findViewById(R.id.home_wallpaper_title); |
| mHomeWallpaperSubtitle1 = metadataView.findViewById(R.id.home_wallpaper_subtitle1); |
| mHomeWallpaperSubtitle2 = metadataView.findViewById(R.id.home_wallpaper_subtitle2); |
| mHomeWallpaperPresentationSection = metadataView.findViewById( |
| R.id.home_wallpaper_presentation_section); |
| mHomeWallpaperExploreButton = |
| metadataView.findViewById(R.id.home_wallpaper_explore_button); |
| mSkipWallpaperButton = metadataView.findViewById(R.id.skip_home_wallpaper); |
| |
| FrameLayout lockWallpaperSection = metadataView.findViewById( |
| R.id.lock_wallpaper_section); |
| lockWallpaperSection.setMinimumWidth(bothWallpaperImageWidth); |
| mLockWallpaperImage = metadataView.findViewById(R.id.lock_wallpaper_image); |
| |
| mLockWallpaperTitle = metadataView.findViewById(R.id.lock_wallpaper_title); |
| mLockWallpaperSubtitle1 = metadataView.findViewById(R.id.lock_wallpaper_subtitle1); |
| mLockWallpaperSubtitle2 = metadataView.findViewById(R.id.lock_wallpaper_subtitle2); |
| mLockWallpaperExploreButton = |
| metadataView.findViewById(R.id.lock_wallpaper_explore_button); |
| } |
| |
| @Override |
| public void bindWallpapers(WallpaperInfo homeWallpaper, WallpaperInfo lockWallpaper, |
| @PresentationMode int presentationMode) { |
| bindHomeWallpaper(homeWallpaper, presentationMode); |
| bindLockWallpaper(lockWallpaper); |
| } |
| |
| private void bindHomeWallpaper(WallpaperInfo homeWallpaper, |
| @PresentationMode int presentationMode) { |
| final Context appContext = getActivity().getApplicationContext(); |
| final UserEventLogger eventLogger = |
| InjectorProvider.getInjector().getUserEventLogger(appContext); |
| |
| mHomeWallpaperInfo = homeWallpaper; |
| |
| homeWallpaper.getThumbAsset(appContext).loadDrawable( |
| getActivity(), mHomeWallpaperImage, |
| getResources().getColor(R.color.secondary_color, getContext().getTheme())); |
| |
| mHomeWallpaperPresentationMode.setText( |
| AttributionFormatter.getHumanReadableWallpaperPresentationMode( |
| appContext, presentationMode)); |
| |
| List<String> attributions = homeWallpaper.getAttributions(appContext); |
| if (!attributions.isEmpty()) { |
| mHomeWallpaperTitle.setText(attributions.get(0)); |
| } |
| if (attributions.size() > 1) { |
| mHomeWallpaperSubtitle1.setText(attributions.get(1)); |
| } |
| if (attributions.size() > 2) { |
| mHomeWallpaperSubtitle2.setText(attributions.get(2)); |
| } |
| |
| final String homeActionUrl = homeWallpaper.getActionUrl(appContext); |
| |
| if (homeActionUrl != null && !homeActionUrl.isEmpty()) { |
| Uri homeExploreUri = Uri.parse(homeActionUrl); |
| |
| ExploreIntentChecker intentChecker = |
| InjectorProvider.getInjector().getExploreIntentChecker(appContext); |
| |
| intentChecker.fetchValidActionViewIntent( |
| homeExploreUri, (@Nullable Intent exploreIntent) -> { |
| if (exploreIntent == null || getActivity() == null) { |
| return; |
| } |
| |
| mHomeWallpaperExploreButton.setVisibility(View.VISIBLE); |
| mHomeWallpaperExploreButton.setImageDrawable(getContext().getDrawable( |
| homeWallpaper.getActionIconRes(appContext))); |
| mHomeWallpaperExploreButton.setContentDescription(getString(homeWallpaper |
| .getActionLabelRes(appContext))); |
| mHomeWallpaperExploreButton.setColorFilter( |
| getResources().getColor(R.color.currently_set_explore_button_color, |
| getContext().getTheme()), |
| Mode.SRC_IN); |
| mHomeWallpaperExploreButton.setOnClickListener(v -> { |
| eventLogger.logActionClicked( |
| mHomeWallpaperInfo.getCollectionId(appContext), |
| mHomeWallpaperInfo.getActionLabelRes(appContext)); |
| startActivity(exploreIntent); |
| }); |
| }); |
| } else { |
| mHomeWallpaperExploreButton.setVisibility(View.GONE); |
| } |
| |
| if (presentationMode == WallpaperPreferences.PRESENTATION_MODE_ROTATING) { |
| mHomeWallpaperPresentationSection.setVisibility(View.VISIBLE); |
| if (Flags.skipDailyWallpaperButtonEnabled) { |
| mSkipWallpaperButton.setVisibility(View.VISIBLE); |
| mSkipWallpaperButton.setColorFilter( |
| getResources().getColor(R.color.currently_set_explore_button_color, |
| getContext().getTheme()), Mode.SRC_IN); |
| mSkipWallpaperButton.setOnClickListener(view -> refreshDailyWallpaper()); |
| } else { |
| mSkipWallpaperButton.setVisibility(View.GONE); |
| } |
| } else { |
| mHomeWallpaperPresentationSection.setVisibility(View.GONE); |
| } |
| |
| mHomeWallpaperImage.setOnClickListener(v -> { |
| eventLogger.logCurrentWallpaperPreviewed(); |
| getFragmentHost().showViewOnlyPreview(mHomeWallpaperInfo); |
| }); |
| } |
| |
| private void bindLockWallpaper(WallpaperInfo lockWallpaper) { |
| if (lockWallpaper == null) { |
| Log.e(TAG, "TwoWallpapersMetadataHolder bound without a lock screen wallpaper."); |
| return; |
| } |
| |
| final Context appContext = getActivity().getApplicationContext(); |
| final UserEventLogger eventLogger = |
| InjectorProvider.getInjector().getUserEventLogger(getActivity()); |
| |
| mLockWallpaperInfo = lockWallpaper; |
| |
| lockWallpaper.getThumbAsset(appContext).loadDrawable( |
| getActivity(), mLockWallpaperImage, getResources().getColor(R.color.secondary_color)); |
| |
| List<String> lockAttributions = lockWallpaper.getAttributions(appContext); |
| if (!lockAttributions.isEmpty()) { |
| mLockWallpaperTitle.setText(lockAttributions.get(0)); |
| } |
| if (lockAttributions.size() > 1) { |
| mLockWallpaperSubtitle1.setText(lockAttributions.get(1)); |
| } |
| if (lockAttributions.size() > 2) { |
| mLockWallpaperSubtitle2.setText(lockAttributions.get(2)); |
| } |
| |
| final String lockActionUrl = lockWallpaper.getActionUrl(appContext); |
| |
| if (lockActionUrl != null && !lockActionUrl.isEmpty()) { |
| Uri lockExploreUri = Uri.parse(lockActionUrl); |
| |
| ExploreIntentChecker intentChecker = |
| InjectorProvider.getInjector().getExploreIntentChecker(appContext); |
| intentChecker.fetchValidActionViewIntent( |
| lockExploreUri, (@Nullable Intent exploreIntent) -> { |
| if (exploreIntent == null || getActivity() == null) { |
| return; |
| } |
| mLockWallpaperExploreButton.setImageDrawable(getContext().getDrawable( |
| lockWallpaper.getActionIconRes(appContext))); |
| mLockWallpaperExploreButton.setContentDescription(getString( |
| lockWallpaper.getActionLabelRes(appContext))); |
| mLockWallpaperExploreButton.setVisibility(View.VISIBLE); |
| mLockWallpaperExploreButton.setColorFilter( |
| getResources().getColor( |
| R.color.currently_set_explore_button_color), |
| Mode.SRC_IN); |
| mLockWallpaperExploreButton.setOnClickListener(new OnClickListener() { |
| @Override |
| public void onClick(View v) { |
| eventLogger.logActionClicked( |
| mLockWallpaperInfo.getCollectionId(appContext), |
| mLockWallpaperInfo.getActionLabelRes(appContext)); |
| startActivity(exploreIntent); |
| } |
| }); |
| }); |
| } else { |
| mLockWallpaperExploreButton.setVisibility(View.GONE); |
| } |
| |
| mLockWallpaperImage.setOnClickListener(new OnClickListener() { |
| @Override |
| public void onClick(View v) { |
| eventLogger.logCurrentWallpaperPreviewed(); |
| getFragmentHost().showViewOnlyPreview(mLockWallpaperInfo); |
| } |
| }); |
| } |
| } |
| |
| private class PreviewPagerAdapter extends PagerAdapter { |
| |
| private List<View> mPages; |
| |
| PreviewPagerAdapter(List<View> pages) { |
| mPages = pages; |
| } |
| |
| @Override |
| public void destroyItem(@NonNull ViewGroup container, int position, |
| @NonNull Object object) { |
| container.removeView((View) object); |
| } |
| |
| @NonNull |
| @Override |
| public Object instantiateItem(@NonNull ViewGroup container, int position) { |
| View view = mPages.get(position); |
| container.addView(view); |
| return view; |
| } |
| |
| @Override |
| public int getCount() { |
| return mPages.size(); |
| } |
| |
| @Override |
| public boolean isViewFromObject(@NonNull View view, @NonNull Object o) { |
| return view == o; |
| } |
| } |
| } |