1 /*
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  */
16 package com.android.wallpaper.picker.individual;
17 
18 import static com.android.wallpaper.picker.WallpaperPickerDelegate.PREVIEW_LIVE_WALLPAPER_REQUEST_CODE;
19 import static com.android.wallpaper.picker.WallpaperPickerDelegate.PREVIEW_WALLPAPER_REQUEST_CODE;
20 
21 import android.app.Activity;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.res.Resources.NotFoundException;
25 import android.os.Bundle;
26 import android.util.Log;
27 import android.view.MenuItem;
28 import android.widget.Toast;
29 
30 import androidx.appcompat.widget.Toolbar;
31 import androidx.fragment.app.Fragment;
32 import androidx.fragment.app.FragmentManager;
33 
34 import com.android.wallpaper.R;
35 import com.android.wallpaper.model.Category;
36 import com.android.wallpaper.model.CategoryProvider;
37 import com.android.wallpaper.model.CategoryReceiver;
38 import com.android.wallpaper.model.InlinePreviewIntentFactory;
39 import com.android.wallpaper.model.LiveWallpaperInfo;
40 import com.android.wallpaper.model.PickerIntentFactory;
41 import com.android.wallpaper.model.WallpaperCategory;
42 import com.android.wallpaper.model.WallpaperInfo;
43 import com.android.wallpaper.module.Injector;
44 import com.android.wallpaper.module.InjectorProvider;
45 import com.android.wallpaper.module.WallpaperPersister;
46 import com.android.wallpaper.picker.BaseActivity;
47 import com.android.wallpaper.picker.PreviewActivity.PreviewActivityIntentFactory;
48 import com.android.wallpaper.util.DiskBasedLogger;
49 import com.android.wallpaper.util.ResourceUtils;
50 import com.android.wallpaper.widget.BottomActionBar;
51 import com.android.wallpaper.widget.BottomActionBar.BottomActionBarHost;
52 
53 /**
54  * Activity that can be launched from the Android wallpaper picker and allows users to pick from
55  * various wallpapers and enter a preview mode for specific ones.
56  */
57 public class IndividualPickerActivity extends BaseActivity implements BottomActionBarHost,
58         IndividualPickerFragment.IndividualPickerFragmentHost {
59     private static final String TAG = "IndividualPickerAct";
60     private static final String EXTRA_CATEGORY_COLLECTION_ID =
61             "com.android.wallpaper.category_collection_id";
62     private static final String EXTRA_WALLPAPER_ID = "com.android.wallpaper.wallpaper_id";
63     private static final String KEY_CATEGORY_COLLECTION_ID = "key_category_collection_id";
64 
65     private InlinePreviewIntentFactory mPreviewIntentFactory;
66     private WallpaperPersister mWallpaperPersister;
67     private Category mCategory;
68     private String mCategoryCollectionId;
69     private String mWallpaperId;
70 
71     @Override
onCreate(Bundle savedInstanceState)72     protected void onCreate(Bundle savedInstanceState) {
73         super.onCreate(savedInstanceState);
74 
75         mPreviewIntentFactory = new PreviewActivityIntentFactory();
76         Injector injector = InjectorProvider.getInjector();
77         mWallpaperPersister = injector.getWallpaperPersister(this);
78 
79         mCategoryCollectionId = (savedInstanceState == null)
80                 ? getIntent().getStringExtra(EXTRA_CATEGORY_COLLECTION_ID)
81                 : savedInstanceState.getString(KEY_CATEGORY_COLLECTION_ID);
82         mWallpaperId = getIntent().getStringExtra(EXTRA_WALLPAPER_ID);
83 
84         if (mWallpaperId == null) { // Normal case
85             initializeUI();
86         } else { // Deeplink to preview page case
87             setContentView(R.layout.activity_loading);
88         }
89 
90         CategoryProvider categoryProvider = injector.getCategoryProvider(this);
91         categoryProvider.fetchCategories(new CategoryReceiver() {
92             @Override
93             public void onCategoryReceived(Category category) {
94                 // Do nothing.
95             }
96 
97             @Override
98             public void doneFetchingCategories() {
99                 mCategory = categoryProvider.getCategory(mCategoryCollectionId);
100                 if (mCategory == null) {
101                     DiskBasedLogger.e(TAG, "Failed to find the category: "
102                             + mCategoryCollectionId, IndividualPickerActivity.this);
103                     // We either were called with an invalid collection Id, or we're restarting
104                     // with no saved state, or with a collection id that doesn't exist anymore.
105                     // In those cases, we cannot continue, so let's just go back.
106                     finish();
107                     return;
108                 }
109 
110                 // Show the preview of the specific wallpaper directly.
111                 if (mWallpaperId != null) {
112                     ((WallpaperCategory) mCategory).fetchWallpapers(getApplicationContext(),
113                             wallpapers -> {
114                                 for (WallpaperInfo wallpaper : wallpapers) {
115                                     if (wallpaper.getWallpaperId().equals(mWallpaperId)) {
116                                         showPreview(wallpaper);
117                                         return;
118                                     }
119                                 }
120                                 // No matched wallpaper, finish the activity.
121                                 finish();
122                             }, false);
123                 } else {
124                     onCategoryLoaded();
125                 }
126             }
127         }, false);
128     }
129 
onCategoryLoaded()130     private void onCategoryLoaded() {
131         setTitle(mCategory.getTitle());
132         getSupportActionBar().setTitle(mCategory.getTitle());
133     }
134 
initializeUI()135     private void initializeUI() {
136         setContentView(R.layout.activity_individual_picker);
137 
138         // Set toolbar as the action bar.
139         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
140         setSupportActionBar(toolbar);
141 
142         FragmentManager fm = getSupportFragmentManager();
143         Fragment fragment = fm.findFragmentById(R.id.fragment_container);
144 
145         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
146 
147         toolbar.getNavigationIcon().setTint(
148                 ResourceUtils.getColorAttr(this, android.R.attr.textColorPrimary)
149         );
150         toolbar.getNavigationIcon().setAutoMirrored(true);
151 
152         if (fragment == null) {
153             fragment = InjectorProvider.getInjector()
154                     .getIndividualPickerFragment(mCategoryCollectionId);
155             fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
156         }
157     }
158 
159     @Override
onOptionsItemSelected(MenuItem item)160     public boolean onOptionsItemSelected(MenuItem item) {
161         int id = item.getItemId();
162         if (id == android.R.id.home) {
163             // Handle Up as a Global back since the only entry point to IndividualPickerActivity is
164             // from TopLevelPickerActivity.
165             onBackPressed();
166             return true;
167         }
168         return false;
169     }
170 
171     @Override
onActivityResult(int requestCode, int resultCode, Intent data)172     public void onActivityResult(int requestCode, int resultCode, Intent data) {
173         super.onActivityResult(requestCode, resultCode, data);
174 
175         boolean shouldShowMessage = false;
176         switch (requestCode) {
177             case PREVIEW_LIVE_WALLPAPER_REQUEST_CODE:
178                 shouldShowMessage = true;
179             case PREVIEW_WALLPAPER_REQUEST_CODE:
180                 if (resultCode == Activity.RESULT_OK) {
181                     mWallpaperPersister.onLiveWallpaperSet();
182 
183                     // The wallpaper was set, so finish this activity with result OK.
184                     finishWithResultOk(shouldShowMessage);
185                 }
186                 break;
187             default:
188                 Log.e(TAG, "Invalid request code: " + requestCode);
189         }
190 
191         // In deeplink to preview page case, this activity is just a middle layer
192         // which redirects to preview activity. We should make sure this activity is finished
193         // after getting the result in this case. Otherwise it will show an empty activity.
194         if (mWallpaperId != null && !isFinishing()) {
195             setResult(resultCode);
196             finish();
197         }
198     }
199 
200     /**
201      * Shows the preview activity for the given wallpaper.
202      */
showPreview(WallpaperInfo wallpaperInfo)203     public void showPreview(WallpaperInfo wallpaperInfo) {
204         mWallpaperPersister.setWallpaperInfoInPreview(wallpaperInfo);
205         wallpaperInfo.showPreview(this, mPreviewIntentFactory,
206                 wallpaperInfo instanceof LiveWallpaperInfo ? PREVIEW_LIVE_WALLPAPER_REQUEST_CODE
207                         : PREVIEW_WALLPAPER_REQUEST_CODE);
208     }
209 
finishWithResultOk(boolean shouldShowMessage)210     private void finishWithResultOk(boolean shouldShowMessage) {
211         if (shouldShowMessage) {
212             try {
213                 Toast.makeText(this, R.string.wallpaper_set_successfully_message,
214                         Toast.LENGTH_SHORT).show();
215             } catch (NotFoundException e) {
216                 Log.e(TAG, "Could not show toast " + e);
217             }
218         }
219         overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
220         setResult(Activity.RESULT_OK);
221         finish();
222     }
223 
224     @Override
onSaveInstanceState(Bundle bundle)225     protected void onSaveInstanceState(Bundle bundle) {
226         super.onSaveInstanceState(bundle);
227 
228         bundle.putString(KEY_CATEGORY_COLLECTION_ID, mCategoryCollectionId);
229     }
230 
231     @Override
getBottomActionBar()232     public BottomActionBar getBottomActionBar() {
233         return findViewById(R.id.bottom_actionbar);
234     }
235 
236     @Override
isHostToolbarShown()237     public boolean isHostToolbarShown() {
238         return true;
239     }
240 
241     @Override
setToolbarTitle(CharSequence title)242     public void setToolbarTitle(CharSequence title) {
243         setTitle(title);
244         getSupportActionBar().setTitle(title);
245     }
246 
247     @Override
setToolbarMenu(int menuResId)248     public void setToolbarMenu(int menuResId) {
249 
250     }
251 
252     @Override
removeToolbarMenu()253     public void removeToolbarMenu() {
254 
255     }
256 
257     @Override
moveToPreviousFragment()258     public void moveToPreviousFragment() {
259         getSupportFragmentManager().popBackStack();
260     }
261 
262     /**
263      * Default implementation of intent factory that provides an intent to start an
264      * IndividualPickerActivity.
265      */
266     public static class IndividualPickerActivityIntentFactory implements PickerIntentFactory {
267         @Override
newIntent(Context ctx, String collectionId)268         public Intent newIntent(Context ctx, String collectionId) {
269             return new Intent(ctx, IndividualPickerActivity.class).putExtra(
270                     EXTRA_CATEGORY_COLLECTION_ID, collectionId);
271         }
272     }
273 }
274