1 /*
2  * Copyright (C) 2016 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 
17 package com.android.storagemanager.deletionhelper;
18 
19 import android.app.Activity;
20 import android.app.Fragment;
21 import android.app.FragmentManager;
22 import android.os.Bundle;
23 import android.provider.Settings;
24 import android.text.SpannableString;
25 import android.text.Spanned;
26 import android.text.TextPaint;
27 import android.text.style.ClickableSpan;
28 import android.view.Menu;
29 import android.view.MenuInflater;
30 import android.view.MenuItem;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.widget.Button;
34 import android.widget.TextView.BufferType;
35 import com.android.settingslib.widget.LinkTextView;
36 import com.android.storagemanager.ButtonBarProvider;
37 import com.android.storagemanager.R;
38 import com.android.storagemanager.utils.Utils;
39 
40 /**
41  * The DeletionHelperActivity is an activity for deleting apps, photos, and downloaded files which
42  * have not been recently used.
43  */
44 public class DeletionHelperActivity extends Activity implements ButtonBarProvider {
45     private static final int ENABLED = 1;
46 
47     private ViewGroup mButtonBar;
48     private Button mNextButton, mSkipButton;
49     private DeletionHelperSettings mFragment;
50     private boolean mIsShowingInterstitial;
51 
52     @Override
onCreate(Bundle savedInstanceState)53     protected void onCreate(Bundle savedInstanceState) {
54         super.onCreate(savedInstanceState);
55         setContentView(R.layout.settings_main_prefs);
56 
57         setIsEmptyState(false /* isEmptyState */);
58 
59         // If we are not returning from an existing activity, create a new fragment.
60         if (savedInstanceState == null) {
61             FragmentManager manager = getFragmentManager();
62             mFragment = DeletionHelperSettings.newInstance(AppsAsyncLoader.NORMAL_THRESHOLD);
63             manager.beginTransaction().replace(R.id.main_content, mFragment).commit();
64         }
65         SpannableString linkText =
66                 new SpannableString(
67                         getString(R.string.empty_state_review_items_link).toUpperCase());
68         LinkTextView emptyStateLink = (LinkTextView) findViewById(R.id.all_items_link);
69         linkText = NoThresholdSpan.linkify(linkText, this);
70         emptyStateLink.setText(linkText, BufferType.SPANNABLE);
71 
72         mButtonBar = (ViewGroup) findViewById(R.id.button_bar);
73         mNextButton = (Button) findViewById(R.id.next_button);
74         mSkipButton = (Button) findViewById(R.id.skip_button);
75 
76         getActionBar().setDisplayHomeAsUpEnabled(true);
77     }
78 
79     @Override
onRequestPermissionsResult( int requestCode, String permissions[], int[] grantResults)80     public void onRequestPermissionsResult(
81             int requestCode, String permissions[], int[] grantResults) {
82         super.onRequestPermissionsResult(requestCode, permissions, grantResults);
83         mFragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
84     }
85 
setIsEmptyState(boolean isEmptyState)86     void setIsEmptyState(boolean isEmptyState) {
87         final View emptyContent = findViewById(R.id.empty_state);
88         final View mainContent = findViewById(R.id.main_content);
89 
90         // Update UI
91         mainContent.setVisibility(isEmptyState ? View.GONE : View.VISIBLE);
92         emptyContent.setVisibility(isEmptyState ? View.VISIBLE : View.GONE);
93         findViewById(R.id.button_bar).setVisibility(isEmptyState ? View.GONE : View.VISIBLE);
94         setTitle(isEmptyState ? R.string.empty_state_title : R.string.deletion_helper_title);
95 
96         // We are giving the user the option to show all in the interstitial, so let's hide the
97         // overflow for this. (Also, the overflow's functions are busted while the empty view is
98         // showing, so this also works around this bug.)
99         mIsShowingInterstitial = isEmptyState && emptyContent.getVisibility() != View.VISIBLE;
100         invalidateOptionsMenu();
101     }
102 
isLoadingVisible()103     public boolean isLoadingVisible() {
104         View loading_container = findViewById(R.id.loading_container);
105         if (loading_container != null) {
106             return loading_container.getVisibility() == View.VISIBLE;
107         }
108         return false;
109     }
110 
setLoading(View listView, boolean loading, boolean animate)111     public void setLoading(View listView, boolean loading, boolean animate) {
112         View loading_container = findViewById(R.id.loading_container);
113         Utils.handleLoadingContainer(loading_container, listView, !loading, animate);
114         getButtonBar().setVisibility(loading ? View.GONE : View.VISIBLE);
115     }
116 
117     @Override
getButtonBar()118     public ViewGroup getButtonBar() {
119         return mButtonBar;
120     }
121 
122     @Override
getNextButton()123     public Button getNextButton() {
124         return mNextButton;
125     }
126 
127     @Override
getSkipButton()128     public Button getSkipButton() {
129         return mSkipButton;
130     }
131 
132     @Override
onCreateOptionsMenu(Menu menu)133     public boolean onCreateOptionsMenu(Menu menu) {
134         final int isNonthresholdAvailable =
135                 Settings.Global.getInt(
136                         getContentResolver(),
137                         Settings.Global.ENABLE_DELETION_HELPER_NO_THRESHOLD_TOGGLE,
138                         ENABLED);
139         if (isNonthresholdAvailable < ENABLED || mIsShowingInterstitial) {
140             return false;
141         }
142 
143         MenuInflater inflater = getMenuInflater();
144         inflater.inflate(R.menu.deletion_helper_settings_menu, menu);
145         return true;
146     }
147 
148     @Override
onOptionsItemSelected(MenuItem item)149     public boolean onOptionsItemSelected(MenuItem item) {
150         FragmentManager manager = getFragmentManager();
151         int thresholdType;
152         switch (item.getItemId()) {
153             case R.id.no_threshold:
154                 thresholdType = AppStateUsageStatsBridge.NO_THRESHOLD;
155                 break;
156             case R.id.default_threshold:
157                 thresholdType = AppStateUsageStatsBridge.NORMAL_THRESHOLD;
158                 break;
159             default:
160                 return super.onOptionsItemSelected(item);
161         }
162 
163         mFragment = DeletionHelperSettings.newInstance(thresholdType);
164         manager.beginTransaction().replace(R.id.main_content, mFragment).commit();
165         return true;
166     }
167 
168     @Override
onNavigateUp()169     public boolean onNavigateUp() {
170         finish();
171         return true;
172     }
173 
174     private static class NoThresholdSpan extends ClickableSpan {
175         private final DeletionHelperActivity mParent;
176 
NoThresholdSpan(DeletionHelperActivity parent)177         public NoThresholdSpan(DeletionHelperActivity parent) {
178             super();
179             mParent = parent;
180         }
181 
182         @Override
onClick(View widget)183         public void onClick(View widget) {
184             FragmentManager manager = mParent.getFragmentManager();
185             Fragment fragment = DeletionHelperSettings.newInstance(AppsAsyncLoader.NO_THRESHOLD);
186             manager.beginTransaction().replace(R.id.main_content, fragment).commit();
187             mParent.setIsEmptyState(false);
188         }
189 
190         @Override
updateDrawState(TextPaint ds)191         public void updateDrawState(TextPaint ds) {
192             super.updateDrawState(ds);
193             // Remove underline
194             ds.setUnderlineText(false);
195         }
196 
197         /**
198          * This method takes a string and turns it into a url span that will launch a
199          * SupportSystemInformationDialogFragment
200          *
201          * @param msg The text to turn into a link
202          * @param parent The dialog the text is in
203          * @return A CharSequence containing the original text content as a url
204          */
linkify(SpannableString msg, DeletionHelperActivity parent)205         public static SpannableString linkify(SpannableString msg, DeletionHelperActivity parent) {
206             NoThresholdSpan link = new NoThresholdSpan(parent);
207             msg.setSpan(link, 0, msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
208             return msg;
209         }
210     }
211 }