ShareWithActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.app.PendingIntent;
  4import android.content.Intent;
  5import android.net.Uri;
  6import android.os.Bundle;
  7import android.util.Log;
  8import android.view.Menu;
  9import android.view.MenuItem;
 10import android.view.View;
 11import android.widget.AdapterView;
 12import android.widget.AdapterView.OnItemClickListener;
 13import android.widget.ListView;
 14import android.widget.Toast;
 15
 16import java.net.URLConnection;
 17import java.util.ArrayList;
 18import java.util.Iterator;
 19import java.util.List;
 20import java.util.concurrent.atomic.AtomicInteger;
 21
 22import eu.siacs.conversations.Config;
 23import eu.siacs.conversations.R;
 24import eu.siacs.conversations.entities.Account;
 25import eu.siacs.conversations.entities.Conversation;
 26import eu.siacs.conversations.entities.Message;
 27import eu.siacs.conversations.persistance.FileBackend;
 28import eu.siacs.conversations.services.XmppConnectionService;
 29import eu.siacs.conversations.ui.adapter.ConversationAdapter;
 30import eu.siacs.conversations.xmpp.XmppConnection;
 31import eu.siacs.conversations.xmpp.jid.InvalidJidException;
 32import eu.siacs.conversations.xmpp.jid.Jid;
 33
 34public class ShareWithActivity extends XmppActivity implements XmppConnectionService.OnConversationUpdate {
 35
 36	private boolean mReturnToPrevious = false;
 37
 38	@Override
 39	public void onConversationUpdate() {
 40		refreshUi();
 41	}
 42
 43	private class Share {
 44		public List<Uri> uris = new ArrayList<>();
 45		public boolean image;
 46		public String account;
 47		public String contact;
 48		public String text;
 49		public String uuid;
 50		public boolean multiple = false;
 51	}
 52
 53	private Share share;
 54
 55	private static final int REQUEST_START_NEW_CONVERSATION = 0x0501;
 56	private ListView mListView;
 57	private ConversationAdapter mAdapter;
 58	private List<Conversation> mConversations = new ArrayList<>();
 59	private Toast mToast;
 60	private AtomicInteger attachmentCounter = new AtomicInteger(0);
 61
 62	private UiInformableCallback<Message> attachFileCallback = new UiInformableCallback<Message>() {
 63
 64		@Override
 65		public void inform(final String text) {
 66			runOnUiThread(new Runnable() {
 67				@Override
 68				public void run() {
 69					replaceToast(text);
 70				}
 71			});
 72		}
 73
 74		@Override
 75		public void userInputRequried(PendingIntent pi, Message object) {
 76			// TODO Auto-generated method stub
 77
 78		}
 79
 80		@Override
 81		public void success(final Message message) {
 82			xmppConnectionService.sendMessage(message);
 83			runOnUiThread(new Runnable() {
 84				@Override
 85				public void run() {
 86					if (attachmentCounter.decrementAndGet() <=0 ) {
 87						int resId;
 88						if (share.image && share.multiple) {
 89							resId = R.string.shared_images_with_x;
 90						} else if (share.image) {
 91							resId = R.string.shared_image_with_x;
 92						} else {
 93							resId = R.string.shared_file_with_x;
 94						}
 95						replaceToast(getString(resId, message.getConversation().getName()));
 96						if (mReturnToPrevious) {
 97							finish();
 98						} else {
 99							switchToConversation(message.getConversation());
100						}
101					}
102				}
103			});
104		}
105
106		@Override
107		public void error(final int errorCode, Message object) {
108			runOnUiThread(new Runnable() {
109				@Override
110				public void run() {
111					replaceToast(getString(errorCode));
112					if (attachmentCounter.decrementAndGet() <=0 ) {
113						finish();
114					}
115				}
116			});
117		}
118	};
119
120	protected void hideToast() {
121		if (mToast != null) {
122			mToast.cancel();
123		}
124	}
125
126	protected void replaceToast(String msg) {
127		hideToast();
128		mToast = Toast.makeText(this, msg ,Toast.LENGTH_LONG);
129		mToast.show();
130	}
131
132	protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
133		super.onActivityResult(requestCode, resultCode, data);
134		if (requestCode == REQUEST_START_NEW_CONVERSATION
135				&& resultCode == RESULT_OK) {
136			share.contact = data.getStringExtra("contact");
137			share.account = data.getStringExtra(EXTRA_ACCOUNT);
138		}
139		if (xmppConnectionServiceBound
140				&& share != null
141				&& share.contact != null
142				&& share.account != null) {
143			share();
144		}
145	}
146
147	@Override
148	protected void onCreate(Bundle savedInstanceState) {
149		super.onCreate(savedInstanceState);
150
151		if (getActionBar() != null) {
152			getActionBar().setDisplayHomeAsUpEnabled(false);
153			getActionBar().setHomeButtonEnabled(false);
154		}
155
156		setContentView(R.layout.share_with);
157		setTitle(getString(R.string.title_activity_sharewith));
158
159		mListView = (ListView) findViewById(R.id.choose_conversation_list);
160		mAdapter = new ConversationAdapter(this, this.mConversations);
161		mListView.setAdapter(mAdapter);
162		mListView.setOnItemClickListener(new OnItemClickListener() {
163
164			@Override
165			public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
166				share(mConversations.get(position));
167			}
168		});
169
170		this.share = new Share();
171	}
172
173	@Override
174	public boolean onCreateOptionsMenu(Menu menu) {
175		getMenuInflater().inflate(R.menu.share_with, menu);
176		return true;
177	}
178
179	@Override
180	public boolean onOptionsItemSelected(final MenuItem item) {
181		switch (item.getItemId()) {
182			case R.id.action_add:
183				final Intent intent = new Intent(getApplicationContext(), ChooseContactActivity.class);
184				startActivityForResult(intent, REQUEST_START_NEW_CONVERSATION);
185				return true;
186		}
187		return super.onOptionsItemSelected(item);
188	}
189
190	@Override
191	public void onStart() {
192		super.onStart();
193		Intent intent = getIntent();
194		if (intent == null) {
195			return;
196		}
197		this.mReturnToPrevious = getPreferences().getBoolean("return_to_previous", getResources().getBoolean(R.bool.return_to_previous));
198		final String type = intent.getType();
199		final String action = intent.getAction();
200		Log.d(Config.LOGTAG, "action: "+action+ ", type:"+type);
201		share.uuid = intent.getStringExtra("uuid");
202		if (Intent.ACTION_SEND.equals(action)) {
203			final String text = intent.getStringExtra(Intent.EXTRA_TEXT);
204			final Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
205			if (type != null && uri != null && (text == null || !type.equals("text/plain"))) {
206				this.share.uris.clear();
207				this.share.uris.add(uri);
208				this.share.image = type.startsWith("image/") || isImage(uri);
209			} else {
210				this.share.text = text;
211			}
212		} else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
213			this.share.image = type != null && type.startsWith("image/");
214			if (!this.share.image) {
215				return;
216			}
217			this.share.uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
218		}
219		if (xmppConnectionServiceBound) {
220			if (share.uuid != null) {
221				share();
222			} else {
223				xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uris.size() == 0);
224			}
225		}
226
227	}
228
229	protected boolean isImage(Uri uri) {
230		try {
231			String guess = URLConnection.guessContentTypeFromName(uri.toString());
232			return (guess != null && guess.startsWith("image/"));
233		} catch (final StringIndexOutOfBoundsException ignored) {
234			return false;
235		}
236	}
237
238	@Override
239	void onBackendConnected() {
240		if (xmppConnectionServiceBound && share != null
241				&& ((share.contact != null && share.account != null) || share.uuid != null)) {
242			share();
243			return;
244		}
245		refreshUiReal();
246	}
247
248	private void share() {
249		final Conversation conversation;
250		if (share.uuid != null) {
251			conversation = xmppConnectionService.findConversationByUuid(share.uuid);
252			if (conversation == null) {
253				return;
254			}
255		}else{
256			Account account;
257			try {
258				account = xmppConnectionService.findAccountByJid(Jid.fromString(share.account));
259			} catch (final InvalidJidException e) {
260				account = null;
261			}
262			if (account == null) {
263				return;
264			}
265
266			try {
267				conversation = xmppConnectionService
268						.findOrCreateConversation(account, Jid.fromString(share.contact), false,true);
269			} catch (final InvalidJidException e) {
270				return;
271			}
272		}
273		share(conversation);
274	}
275
276	private void share(final Conversation conversation) {
277		final Account account = conversation.getAccount();
278		final XmppConnection connection = account.getXmppConnection();
279		final long max = connection == null ? -1 : connection.getFeatures().getMaxHttpUploadSize();
280		mListView.setEnabled(false);
281		if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP && !hasPgp()) {
282			if (share.uuid == null) {
283				showInstallPgpDialog();
284			} else {
285				Toast.makeText(this,R.string.openkeychain_not_installed,Toast.LENGTH_SHORT).show();
286				finish();
287			}
288			return;
289		}
290		if (share.uris.size() != 0) {
291			OnPresenceSelected callback = new OnPresenceSelected() {
292				@Override
293				public void onPresenceSelected() {
294					attachmentCounter.set(share.uris.size());
295					if (share.image) {
296						share.multiple = share.uris.size() > 1;
297						replaceToast(getString(share.multiple ? R.string.preparing_images : R.string.preparing_image));
298						for (Iterator<Uri> i = share.uris.iterator(); i.hasNext(); i.remove()) {
299							ShareWithActivity.this.xmppConnectionService
300									.attachImageToConversation(conversation, i.next(),
301											attachFileCallback);
302						}
303					} else {
304						replaceToast(getString(R.string.preparing_file));
305						ShareWithActivity.this.xmppConnectionService
306								.attachFileToConversation(conversation, share.uris.get(0), attachFileCallback);
307					}
308				}
309			};
310			if (account.httpUploadAvailable()
311					&& ((share.image && !neverCompressPictures())
312					|| conversation.getMode() == Conversation.MODE_MULTI
313					|| FileBackend.allFilesUnderSize(this, share.uris, max))
314					&& conversation.getNextEncryption() != Message.ENCRYPTION_OTR) {
315				callback.onPresenceSelected();
316			} else {
317				selectPresence(conversation, callback);
318			}
319		} else {
320			if (mReturnToPrevious && this.share.text != null && !this.share.text.isEmpty() ) {
321				final OnPresenceSelected callback = new OnPresenceSelected() {
322
323					private void finishAndSend(Message message) {
324						xmppConnectionService.sendMessage(message);
325						replaceToast(getString(R.string.shared_text_with_x, conversation.getName()));
326						finish();
327					}
328
329					private UiCallback<Message> messageEncryptionCallback = new UiCallback<Message>() {
330						@Override
331						public void success(final Message message) {
332							message.setEncryption(Message.ENCRYPTION_DECRYPTED);
333							runOnUiThread(new Runnable() {
334								@Override
335								public void run() {
336									finishAndSend(message);
337								}
338							});
339						}
340
341						@Override
342						public void error(final int errorCode, Message object) {
343							runOnUiThread(new Runnable() {
344								@Override
345								public void run() {
346									replaceToast(getString(errorCode));
347									finish();
348								}
349							});
350						}
351
352						@Override
353						public void userInputRequried(PendingIntent pi, Message object) {
354							finish();
355						}
356					};
357
358					@Override
359					public void onPresenceSelected() {
360
361						final int encryption = conversation.getNextEncryption();
362
363						Message message = new Message(conversation,share.text, encryption);
364
365						Log.d(Config.LOGTAG,"on presence selected encrpytion="+encryption);
366
367						if (encryption == Message.ENCRYPTION_PGP) {
368							replaceToast(getString(R.string.encrypting_message));
369							xmppConnectionService.getPgpEngine().encrypt(message,messageEncryptionCallback);
370							return;
371						}
372
373						if (encryption == Message.ENCRYPTION_OTR) {
374							message.setCounterpart(conversation.getNextCounterpart());
375						}
376						finishAndSend(message);
377					}
378				};
379				if (conversation.getNextEncryption() == Message.ENCRYPTION_OTR) {
380					selectPresence(conversation, callback);
381				} else {
382					callback.onPresenceSelected();
383				}
384			} else {
385				switchToConversation(conversation, this.share.text, true);
386			}
387		}
388
389	}
390
391	public void refreshUiReal() {
392		xmppConnectionService.populateWithOrderedConversations(mConversations, this.share != null && this.share.uris.size() == 0);
393		mAdapter.notifyDataSetChanged();
394	}
395
396	@Override
397	public void onBackPressed() {
398		if (attachmentCounter.get() >= 1) {
399			replaceToast(getString(R.string.sharing_files_please_wait));
400		} else {
401			super.onBackPressed();
402		}
403	}
404}