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