-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnew_AboutHomePromoBox.java
More file actions
199 lines (176 loc) · 7.24 KB
/
new_AboutHomePromoBox.java
File metadata and controls
199 lines (176 loc) · 7.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.sync.setup.activities.SetupSyncActivity;
import org.mozilla.gecko.sync.setup.SyncAccounts;
import org.mozilla.gecko.util.GeckoAsyncTask;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Random;
/**
* A promotional box for the about:home page. The layout contains an ImageView to the left of a
* TextView whose resources may be overidden to display custom values for a new type of promo box.
* To do this, add a new Type value and update show() to call setResources() for your values -
* including a set[Box Type]Resources() helper method is recommended.
*/
public class AboutHomePromoBox extends TextView implements View.OnClickListener {
private static final String LOGTAG = "GeckoAboutHomePromoBox";
/* Small class for implementing a new promo box type. Implementors should override canShow and onClick
* to handle their own needs. By default the box is always showable and does nothing when clicked.
*/
public static class Type {
public int text;
public int boldText;
public int image;
public Type(int aText, int aBoldText, int aImage) {
text = aText;
boldText = aBoldText;
image = aImage;
}
public boolean canShow() {
return true;
}
public void onClick(View v) { }
}
private class SyncType extends Type {
private OnAccountsUpdateListener mAccountListener;
public SyncType(int aText, int aBoldText, int aImage) {
super(aText, aBoldText, aImage);
// The listener will run on the background thread (see 2nd argument)
mAccountListener = new OnAccountsUpdateListener() {
public void onAccountsUpdated(Account[] accounts) {
showRandomPromo();
}
};
AccountManager.get(mContext).addOnAccountsUpdatedListener(mAccountListener, GeckoAppShell.getHandler(), false);
}
@Override
public boolean canShow() {
return !SyncAccounts.syncAccountsExist(mContext);
}
@Override
public void onClick(View v) {
final Context context = v.getContext();
final Intent intent = new Intent(context, SetupSyncActivity.class);
context.startActivity(intent);
}
public void onDestroy() {
if (mAccountListener != null) {
AccountManager.get(mContext).removeOnAccountsUpdatedListener(mAccountListener);
mAccountListener = null;
}
}
}
private ArrayList<Type> mTypes;
private Type mType;
private final Context mContext;
public AboutHomePromoBox(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setOnClickListener(this);
mTypes = new ArrayList<Type>();
mTypes.add(new SyncType(R.string.abouthome_about_sync,
R.string.abouthome_sync_bold_name,
R.drawable.abouthome_promo_logo_sync));
mTypes.add(new Type(R.string.abouthome_about_apps,
R.string.abouthome_apps_bold_name,
R.drawable.abouthome_promo_logo_apps) {
@Override
public boolean canShow() {
final ContentResolver resolver = mContext.getContentResolver();
return !BrowserDB.isVisited(resolver, "https://marketplace.firefox.com/");
}
@Override
public void onClick(View v) {
Tabs.getInstance().loadUrl("https://marketplace.firefox.com/", Tabs.LOADURL_NEW_TAB);
// this isn't as good as being notified whenever this url is added to the database,
// if the user visits the marketplace through some other means, we'll have to wait
// until we are refreshed or restarted to get the correct value
v.postDelayed(new Runnable() {
public void run() {
showRandomPromo();
}
}, 5000);
}
});
}
@Override
public void onClick(View v) {
if (mType != null)
mType.onClick(v);
}
private interface GetTypesCallback {
void onGotTypes(ArrayList<Type> types);
}
/**
* Shows the specified promo box. If a promo box is already active, it will be overidden with a
* promo box of the specified type.
*/
public void showRandomPromo() {
getAvailableTypes(new GetTypesCallback() {
public void onGotTypes(ArrayList<Type> types) {
if (types.size() == 0) {
hide();
return;
}
int idx = new Random().nextInt(types.size());
mType = types.get(idx);
updateViewResources();
setVisibility(View.VISIBLE);
}
});
}
public void hide() {
setVisibility(View.GONE);
mType = null;
}
private void updateViewResources() {
updateTextViewResources();
setCompoundDrawablesWithIntrinsicBounds(mType.image, 0, 0, 0);
}
private void updateTextViewResources() {
final String text = mContext.getResources().getString(mType.text);
final String boldText = mContext.getResources().getString(mType.boldText);
final int styleIndex = text.indexOf(boldText);
if (styleIndex < 0)
setText(text);
else {
final SpannableString spannableText = new SpannableString(text);
spannableText.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), styleIndex, styleIndex + boldText.length(), 0);
setText(spannableText, TextView.BufferType.SPANNABLE);
}
}
private void getAvailableTypes(final GetTypesCallback callback) {
(new GeckoAsyncTask<Void, Void, ArrayList<Type>>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) {
@Override
public ArrayList<Type> doInBackground(Void... params) {
// Run all of this on a background thread
ArrayList<Type> availTypes = new ArrayList<Type>();
for (int i = 0; i < mTypes.size(); i++) {
Type t = mTypes.get(i);
if (t.canShow()) {
availTypes.add(t);
}
}
return availTypes;
}
@Override
public void onPostExecute(ArrayList<Type> types) {
callback.onGotTypes(types);
}
}).execute();
}
}