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         int itemId = item.getItemId();
153         if (itemId == R.id.no_threshold) {
154             thresholdType = AppStateUsageStatsBridge.NO_THRESHOLD;
155         } else if (itemId == R.id.default_threshold) {
156             thresholdType = AppStateUsageStatsBridge.NORMAL_THRESHOLD;
157         } else {
158             return super.onOptionsItemSelected(item);
159         }
160 
161         mFragment = DeletionHelperSettings.newInstance(thresholdType);
162         manager.beginTransaction().replace(R.id.main_content, mFragment).commit();
163         return true;
164     }
165 
166     @Override
onNavigateUp()167     public boolean onNavigateUp() {
168         finish();
169         return true;
170     }
171 
172     private static class NoThresholdSpan extends ClickableSpan {
173         private final DeletionHelperActivity mParent;
174 
NoThresholdSpan(DeletionHelperActivity parent)175         public NoThresholdSpan(DeletionHelperActivity parent) {
176             super();
177             mParent = parent;
178         }
179 
180         @Override
onClick(View widget)181         public void onClick(View widget) {
182             FragmentManager manager = mParent.getFragmentManager();
183             Fragment fragment = DeletionHelperSettings.newInstance(AppsAsyncLoader.NO_THRESHOLD);
184             manager.beginTransaction().replace(R.id.main_content, fragment).commit();
185             mParent.setIsEmptyState(false);
186         }
187 
188         @Override
updateDrawState(TextPaint ds)189         public void updateDrawState(TextPaint ds) {
190             super.updateDrawState(ds);
191             // Remove underline
192             ds.setUnderlineText(false);
193         }
194 
195         /**
196          * This method takes a string and turns it into a url span that will launch a
197          * SupportSystemInformationDialogFragment
198          *
199          * @param msg The text to turn into a link
200          * @param parent The dialog the text is in
201          * @return A CharSequence containing the original text content as a url
202          */
linkify(SpannableString msg, DeletionHelperActivity parent)203         public static SpannableString linkify(SpannableString msg, DeletionHelperActivity parent) {
204             NoThresholdSpan link = new NoThresholdSpan(parent);
205             msg.setSpan(link, 0, msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
206             return msg;
207         }
208     }
209 }
210