1package eu.siacs.conversations.ui;
2
3import android.app.PendingIntent;
4import android.content.Intent;
5import android.content.pm.PackageManager;
6import android.graphics.Bitmap;
7import android.graphics.BitmapFactory;
8import android.net.Uri;
9import android.os.Bundle;
10import android.view.View;
11import android.view.View.OnClickListener;
12import android.view.View.OnLongClickListener;
13import android.widget.Button;
14import android.widget.ImageView;
15import android.widget.TextView;
16import android.widget.Toast;
17
18import com.soundcloud.android.crop.Crop;
19
20import java.io.File;
21import java.io.FileNotFoundException;
22
23import eu.siacs.conversations.Config;
24import eu.siacs.conversations.R;
25import eu.siacs.conversations.entities.Account;
26import eu.siacs.conversations.persistance.FileBackend;
27import eu.siacs.conversations.utils.ExifHelper;
28import eu.siacs.conversations.utils.FileUtils;
29import eu.siacs.conversations.utils.PhoneHelper;
30import eu.siacs.conversations.xmpp.jid.InvalidJidException;
31import eu.siacs.conversations.xmpp.jid.Jid;
32import eu.siacs.conversations.xmpp.pep.Avatar;
33
34public class PublishProfilePictureActivity extends XmppActivity {
35
36 private static final int REQUEST_CHOOSE_FILE = 0xac23;
37 private ImageView avatar;
38 private TextView accountTextView;
39 private TextView hintOrWarning;
40 private TextView secondaryHint;
41 private Button cancelButton;
42 private Button publishButton;
43 private Uri avatarUri;
44 private Uri defaultUri;
45 private Account account;
46 private boolean support = false;
47 private OnLongClickListener backToDefaultListener = new OnLongClickListener() {
48
49 @Override
50 public boolean onLongClick(View v) {
51 avatarUri = defaultUri;
52 loadImageIntoPreview(defaultUri);
53 return true;
54 }
55 };
56 private boolean mInitialAccountSetup;
57 private UiCallback<Avatar> avatarPublication = new UiCallback<Avatar>() {
58
59 @Override
60 public void success(Avatar object) {
61 runOnUiThread(new Runnable() {
62
63 @Override
64 public void run() {
65 if (mInitialAccountSetup) {
66 Intent intent = new Intent(getApplicationContext(),
67 StartConversationActivity.class);
68 intent.putExtra("init", true);
69 startActivity(intent);
70 }
71 Toast.makeText(PublishProfilePictureActivity.this,
72 R.string.avatar_has_been_published,
73 Toast.LENGTH_SHORT).show();
74 finish();
75 }
76 });
77 }
78
79 @Override
80 public void error(final int errorCode, Avatar object) {
81 runOnUiThread(new Runnable() {
82
83 @Override
84 public void run() {
85 hintOrWarning.setText(errorCode);
86 hintOrWarning.setTextColor(getWarningTextColor());
87 publishButton.setText(R.string.publish);
88 enablePublishButton();
89 }
90 });
91
92 }
93
94 @Override
95 public void userInputRequried(PendingIntent pi, Avatar object) {
96 }
97 };
98
99 @Override
100 public void onCreate(Bundle savedInstanceState) {
101 super.onCreate(savedInstanceState);
102 setContentView(R.layout.activity_publish_profile_picture);
103 this.avatar = (ImageView) findViewById(R.id.account_image);
104 this.cancelButton = (Button) findViewById(R.id.cancel_button);
105 this.publishButton = (Button) findViewById(R.id.publish_button);
106 this.accountTextView = (TextView) findViewById(R.id.account);
107 this.hintOrWarning = (TextView) findViewById(R.id.hint_or_warning);
108 this.secondaryHint = (TextView) findViewById(R.id.secondary_hint);
109 this.publishButton.setOnClickListener(new OnClickListener() {
110
111 @Override
112 public void onClick(View v) {
113 if (avatarUri != null) {
114 publishButton.setText(R.string.publishing);
115 disablePublishButton();
116 xmppConnectionService.publishAvatar(account, avatarUri,
117 avatarPublication);
118 }
119 }
120 });
121 this.cancelButton.setOnClickListener(new OnClickListener() {
122
123 @Override
124 public void onClick(View v) {
125 if (mInitialAccountSetup) {
126 Intent intent = new Intent(getApplicationContext(),
127 StartConversationActivity.class);
128 if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1) {
129 intent.putExtra("init", true);
130 }
131 startActivity(intent);
132 }
133 finish();
134 }
135 });
136 this.avatar.setOnClickListener(new OnClickListener() {
137
138 @Override
139 public void onClick(View v) {
140 if (hasStoragePermission(REQUEST_CHOOSE_FILE)) {
141 chooseAvatar();
142 }
143
144 }
145 });
146 this.defaultUri = PhoneHelper.getSefliUri(getApplicationContext());
147 }
148
149 private void chooseAvatar() {
150 Intent attachFileIntent = new Intent();
151 attachFileIntent.setType("image/*");
152 attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
153 Intent chooser = Intent.createChooser(attachFileIntent, getString(R.string.attach_file));
154 startActivityForResult(chooser, REQUEST_CHOOSE_FILE);
155 }
156
157 @Override
158 public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
159 if (grantResults.length > 0)
160 if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
161 if (requestCode == REQUEST_CHOOSE_FILE) {
162 chooseAvatar();
163 }
164 } else {
165 Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show();
166 }
167 }
168
169 @Override
170 protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
171 super.onActivityResult(requestCode, resultCode, data);
172 if (resultCode == RESULT_OK) {
173 switch (requestCode) {
174 case REQUEST_CHOOSE_FILE:
175 Uri source = data.getData();
176 String original = FileUtils.getPath(this, source);
177 if (original != null) {
178 source = Uri.parse("file://"+original);
179 }
180 Uri destination = Uri.fromFile(new File(getCacheDir(), "croppedAvatar"));
181 final int size = getPixel(192);
182 Crop.of(source, destination).asSquare().withMaxSize(size, size).start(this);
183 break;
184 case Crop.REQUEST_CROP:
185 this.avatarUri = Uri.fromFile(new File(getCacheDir(), "croppedAvatar"));
186 loadImageIntoPreview(this.avatarUri);
187 break;
188 }
189 } else {
190 if (requestCode == Crop.REQUEST_CROP && data != null) {
191 Throwable throwable = Crop.getError(data);
192 if (throwable != null && throwable instanceof OutOfMemoryError) {
193 Toast.makeText(this,R.string.selection_too_large, Toast.LENGTH_SHORT).show();
194 }
195 }
196 }
197 }
198
199 @Override
200 protected void onBackendConnected() {
201 if (getIntent() != null) {
202 Jid jid;
203 try {
204 jid = Jid.fromString(getIntent().getStringExtra("account"));
205 } catch (InvalidJidException e) {
206 jid = null;
207 }
208 if (jid != null) {
209 this.account = xmppConnectionService.findAccountByJid(jid);
210 if (this.account.getXmppConnection() != null) {
211 this.support = this.account.getXmppConnection().getFeatures().pep();
212 }
213 if (this.avatarUri == null) {
214 if (this.account.getAvatar() != null
215 || this.defaultUri == null) {
216 this.avatar.setImageBitmap(avatarService().get(account, getPixel(192)));
217 if (this.defaultUri != null) {
218 this.avatar
219 .setOnLongClickListener(this.backToDefaultListener);
220 } else {
221 this.secondaryHint.setVisibility(View.INVISIBLE);
222 }
223 if (!support) {
224 this.hintOrWarning
225 .setTextColor(getWarningTextColor());
226 this.hintOrWarning
227 .setText(R.string.error_publish_avatar_no_server_support);
228 }
229 } else {
230 this.avatarUri = this.defaultUri;
231 loadImageIntoPreview(this.defaultUri);
232 this.secondaryHint.setVisibility(View.INVISIBLE);
233 }
234 } else {
235 loadImageIntoPreview(avatarUri);
236 }
237 String account;
238 if (Config.DOMAIN_LOCK != null) {
239 account = this.account.getJid().getLocalpart();
240 } else {
241 account = this.account.getJid().toBareJid().toString();
242 }
243 this.accountTextView.setText(account);
244 }
245 }
246
247 }
248
249 @Override
250 protected void onStart() {
251 super.onStart();
252 if (getIntent() != null) {
253 this.mInitialAccountSetup = getIntent().getBooleanExtra("setup", false);
254 }
255 if (this.mInitialAccountSetup) {
256 this.cancelButton.setText(R.string.skip);
257 }
258 }
259
260 private Bitmap loadScaledBitmap(Uri uri, int reqSize) throws FileNotFoundException {
261 final BitmapFactory.Options options = new BitmapFactory.Options();
262 options.inJustDecodeBounds = true;
263 BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
264 int rotation = ExifHelper.getOrientation(getContentResolver().openInputStream(uri));
265 options.inSampleSize = FileBackend.calcSampleSize(options, reqSize);
266 options.inJustDecodeBounds = false;
267 Bitmap bm = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
268 return FileBackend.rotate(bm,rotation);
269 }
270
271 protected void loadImageIntoPreview(Uri uri) {
272 Bitmap bm = null;
273 try {
274 bm = loadScaledBitmap(uri, getPixel(192));
275 } catch (Exception e) {
276 e.printStackTrace();
277 }
278
279 if (bm == null) {
280 disablePublishButton();
281 this.hintOrWarning.setTextColor(getWarningTextColor());
282 this.hintOrWarning
283 .setText(R.string.error_publish_avatar_converting);
284 return;
285 }
286 this.avatar.setImageBitmap(bm);
287 if (support) {
288 enablePublishButton();
289 this.publishButton.setText(R.string.publish);
290 this.hintOrWarning.setText(R.string.publish_avatar_explanation);
291 this.hintOrWarning.setTextColor(getPrimaryTextColor());
292 } else {
293 disablePublishButton();
294 this.hintOrWarning.setTextColor(getWarningTextColor());
295 this.hintOrWarning
296 .setText(R.string.error_publish_avatar_no_server_support);
297 }
298 if (this.defaultUri != null && uri.equals(this.defaultUri)) {
299 this.secondaryHint.setVisibility(View.INVISIBLE);
300 this.avatar.setOnLongClickListener(null);
301 } else if (this.defaultUri != null) {
302 this.secondaryHint.setVisibility(View.VISIBLE);
303 this.avatar.setOnLongClickListener(this.backToDefaultListener);
304 }
305 }
306
307 protected void enablePublishButton() {
308 this.publishButton.setEnabled(true);
309 this.publishButton.setTextColor(getPrimaryTextColor());
310 }
311
312 protected void disablePublishButton() {
313 this.publishButton.setEnabled(false);
314 this.publishButton.setTextColor(getSecondaryTextColor());
315 }
316
317 public void refreshUiReal() {
318 //nothing to do. This Activity doesn't implement any listeners
319 }
320}