diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index b47ee68b8d478ef34ca59df1107eb881abcf119f..bfd82ba9f3f31685d8a3ea480a0b6979f9c9d5d8 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -153,15 +153,15 @@ <string name="introduction_warn_different_identities_title">Warning: Different Identities</string> <string name="introduction_warn_different_identities_text">You are trying to introduce two contacts that you have added with different identities. This might reveal that both identities are yours.</string> <string name="introduction_request_sent">You have asked to introduce %1$s to %2$s.</string> - <string name="introduction_request_received">%1$s introduced you to %2$s. Do you want to add %2$s to your contact list?</string> - <string name="introduction_request_exists_received">%1$s introduced you to %2$s, but %2$s is already in your contact list. Since %1$s might not know that, you can still respond:</string> + <string name="introduction_request_received">%1$s has asked to introduce you to %2$s. Do you want to add %2$s to your contact list?</string> + <string name="introduction_request_exists_received">%1$s has asked to introduce you to %2$s, but %2$s is already in your contact list. Since %1$s might not know that, you can still respond:</string> <string name="introduction_request_answered_received">%1$s has asked to introduce you to %2$s.</string> <string name="introduction_response_accepted_sent">You accepted the introduction to %1$s.</string> <string name="introduction_response_declined_sent">You declined the introduction to %1$s.</string> <string name="introduction_response_accepted_received">%1$s accepted to be introduced to %2$s.</string> <string name="introduction_response_declined_received">%1$s declined to be introduced to %2$s.</string> <string name="introduction_success_title">Introduced contact was added</string> - <string name="introduction_success_text">You have been successfully introduced to %1$s who was now added to your contact list.</string> + <string name="introduction_success_text">You have been introduced to %1$s.</string> <!-- Dialogs --> <string name="dialog_title_lost_password">Lost Password</string> diff --git a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java index 2330aac866a4388a63e3c7d78327d846e0dfb564..17f8fbac79365c602896712e0ceaf7060d379967 100644 --- a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java +++ b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java @@ -15,6 +15,7 @@ import org.briarproject.android.api.AndroidNotificationManager; import org.briarproject.android.contact.ConversationActivity; import org.briarproject.android.forum.ForumActivity; import org.briarproject.api.contact.Contact; +import org.briarproject.api.contact.ContactId; import org.briarproject.api.db.DatabaseExecutor; import org.briarproject.api.db.DbException; import org.briarproject.api.event.Event; @@ -161,21 +162,11 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager, showForumPostNotification(m.getMessage().getGroupId()); } } else if (e instanceof IntroductionRequestReceivedEvent) { - try { - GroupId group = messagingManager.getConversationId( - ((IntroductionRequestReceivedEvent) e).getContactId()); - showPrivateMessageNotification(group); - } catch (DbException ex) { - if (LOG.isLoggable(WARNING)) LOG.log(WARNING, ex.toString(), ex); - } + ContactId c = ((IntroductionRequestReceivedEvent) e).getContactId(); + showIntroductionNotifications(c); } else if (e instanceof IntroductionResponseReceivedEvent) { - try { - GroupId group = messagingManager.getConversationId( - ((IntroductionResponseReceivedEvent) e).getContactId()); - showPrivateMessageNotification(group); - } catch (DbException ex) { - if (LOG.isLoggable(WARNING)) LOG.log(WARNING, ex.toString(), ex); - } + ContactId c = ((IntroductionResponseReceivedEvent) e).getContactId(); + showIntroductionNotifications(c); } else if (e instanceof IntroductionSucceededEvent) { Contact c = ((IntroductionSucceededEvent) e).getContact(); showIntroductionSucceededNotification(c); @@ -367,6 +358,20 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager, }); } + private void showIntroductionNotifications(final ContactId c) { + androidExecutor.execute(new Runnable() { + public void run() { + try { + GroupId group = messagingManager.getConversationId(c); + showPrivateMessageNotification(group); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } + } + }); + } + private void showIntroductionSucceededNotification(final Contact c) { androidExecutor.execute(new Runnable() { public void run() { diff --git a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java index 3cba02fadbe734e9f9ed9c98a9baeeff2ab06c50..f71a93a47739401ddf870c2c824115455d4e92d1 100644 --- a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java +++ b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java @@ -303,6 +303,7 @@ public class ContactListFragment extends BaseEventFragment { if (LOG.isLoggable(INFO)) LOG.info("Loading message headers took " + duration + " ms"); + now = System.currentTimeMillis(); Collection<IntroductionMessage> introductions = introductionManager .getIntroductionMessages(id); diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java index 2d006e681bea924952b921038a3a5d23a16fdfc9..5e97e2130e3e24c96a78658ab8594ae59003e419 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java @@ -90,7 +90,6 @@ public class ConversationActivity extends BriarActivity private static final Logger LOG = Logger.getLogger(ConversationActivity.class.getName()); - private static final int INTRODUCTION_REQUEST_CODE = 0; @Inject protected AndroidNotificationManager notificationManager; @Inject protected ConnectionRegistry connectionRegistry; @@ -128,12 +127,12 @@ public class ConversationActivity extends BriarActivity setContentView(R.layout.activity_conversation); // Custom Toolbar - final Toolbar tb = (Toolbar) findViewById(R.id.toolbar); + Toolbar tb = (Toolbar) findViewById(R.id.toolbar); toolbarAvatar = (CircleImageView) tb.findViewById(R.id.contactAvatar); toolbarStatus = (ImageView) tb.findViewById(R.id.contactStatus); toolbarTitle = (TextView) tb.findViewById(R.id.contactName); setSupportActionBar(tb); - final ActionBar ab = getSupportActionBar(); + ActionBar ab = getSupportActionBar(); if (ab != null) { ab.setDisplayShowHomeEnabled(true); ab.setDisplayHomeAsUpEnabled(true); @@ -202,8 +201,7 @@ public class ConversationActivity extends BriarActivity ActivityOptionsCompat options = ActivityOptionsCompat .makeCustomAnimation(this, android.R.anim.slide_in_left, android.R.anim.slide_out_right); - ActivityCompat.startActivityForResult(this, intent, - INTRODUCTION_REQUEST_CODE, options.toBundle()); + ActivityCompat.startActivity(this, intent, options.toBundle()); return true; case R.id.action_social_remove_person: askToRemoveContact(); @@ -213,17 +211,6 @@ public class ConversationActivity extends BriarActivity } } - @Override - protected void onActivityResult(int requestCode, int resultCode, - Intent data) { - - if (requestCode == INTRODUCTION_REQUEST_CODE) { - if (resultCode == RESULT_OK) { - loadData(); - } - } - } - private void loadData() { runOnDbThread(new Runnable() { public void run() { @@ -274,7 +261,7 @@ public class ConversationActivity extends BriarActivity toolbarStatus .setContentDescription(getString(R.string.offline)); } - adapter.setIdenticonKey(contactIdenticonKey, contactName); + adapter.setContactInformation(contactIdenticonKey, contactName); } }); } @@ -284,6 +271,8 @@ public class ConversationActivity extends BriarActivity public void run() { try { long now = System.currentTimeMillis(); + if (contactId == null) + contactId = messagingManager.getContactId(groupId); Collection<PrivateMessageHeader> headers = messagingManager.getMessageHeaders(contactId); Collection<IntroductionMessage> introductions = @@ -372,11 +361,10 @@ public class ConversationActivity extends BriarActivity if (item.getId().equals(m)) { item.setBody(body); adapter.notifyItemChanged(messages.keyAt(i)); + list.scrollToPosition(adapter.getItemCount() - 1); return; } } - // Scroll to the bottom - list.scrollToPosition(adapter.getItemCount() - 1); } }); } @@ -385,11 +373,9 @@ public class ConversationActivity extends BriarActivity runOnUiThread(new Runnable() { @Override public void run() { - if (adapter != null) { - adapter.add(item); - // Scroll to the bottom - list.scrollToPosition(adapter.getItemCount() - 1); - } + adapter.add(item); + // Scroll to the bottom + list.scrollToPosition(adapter.getItemCount() - 1); } }); } @@ -609,6 +595,10 @@ public class ConversationActivity extends BriarActivity runOnDbThread(new Runnable() { public void run() { try { + // make sure contactId is initialised + if (contactId == null) + contactId = messagingManager.getContactId(groupId); + // remove contact with that ID contactManager.removeContact(contactId); } catch (DbException e) { if (LOG.isLoggable(WARNING)) @@ -657,7 +647,8 @@ public class ConversationActivity extends BriarActivity } @Override - public void respondToIntroduction(final SessionId sessionId, final boolean accept) { + public void respondToIntroduction(final SessionId sessionId, + final boolean accept) { runOnDbThread(new Runnable() { @Override public void run() { @@ -665,9 +656,13 @@ public class ConversationActivity extends BriarActivity timestamp = Math.max(timestamp, getMinTimestampForNewMessage()); try { if (accept) { - introductionManager.acceptIntroduction(contactId, sessionId, timestamp); + introductionManager + .acceptIntroduction(contactId, sessionId, + timestamp); } else { - introductionManager.declineIntroduction(contactId, sessionId, timestamp); + introductionManager + .declineIntroduction(contactId, sessionId, + timestamp); } loadMessages(); } catch (DbException e) { diff --git a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java index 83cb88cb6446c674142af08b5d8f0f2b96ef098d..de62800d1337c511b1b656300dd450c86acf9824 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java @@ -88,21 +88,14 @@ class ConversationAdapter extends RecyclerView.Adapter { IntroductionHandler introductionHandler) { ctx = context; intro = introductionHandler; - setHasStableIds(true); } - public void setIdenticonKey(byte[] key, String contactName) { - this.identiconKey = key; + public void setContactInformation(byte[] identiconKey, String contactName) { + this.identiconKey = identiconKey; this.contactName = contactName; - // FIXME this breaks the progress animation because it is called early before data is loaded notifyDataSetChanged(); } - @Override - public long getItemId(int position) { - return getItem(position).getId().hashCode(); - } - @Override public int getItemViewType(int position) { return getItem(position).getType(); @@ -147,11 +140,10 @@ class ConversationAdapter extends RecyclerView.Adapter { } @Override - public void onBindViewHolder(final ViewHolder ui, final int position) { + public void onBindViewHolder(ViewHolder ui, int position) { ConversationItem item = getItem(position); if (item instanceof ConversationMessageItem) { - bindMessage((MessageHolder) ui, (ConversationMessageItem) item, - position); + bindMessage((MessageHolder) ui, (ConversationMessageItem) item); } else if (item instanceof ConversationIntroductionOutItem) { bindIntroduction((IntroductionHolder) ui, (ConversationIntroductionOutItem) item, position); @@ -159,18 +151,16 @@ class ConversationAdapter extends RecyclerView.Adapter { bindIntroduction((IntroductionHolder) ui, (ConversationIntroductionInItem) item, position); } else if (item instanceof ConversationNoticeOutItem) { - bindNotice((NoticeHolder) ui, (ConversationNoticeOutItem) item, - position); + bindNotice((NoticeHolder) ui, (ConversationNoticeOutItem) item); } else if (item instanceof ConversationNoticeInItem) { - bindNotice((NoticeHolder) ui, (ConversationNoticeInItem) item, - position); + bindNotice((NoticeHolder) ui, (ConversationNoticeInItem) item); } else { throw new IllegalArgumentException("Unhandled Conversation Item"); } } - private void bindMessage(final MessageHolder ui, - ConversationMessageItem item, final int position) { + private void bindMessage(MessageHolder ui, ConversationMessageItem item) { + PrivateMessageHeader header = item.getHeader(); if (item.getType() == MSG_OUT) { @@ -213,7 +203,7 @@ class ConversationAdapter extends RecyclerView.Adapter { ui.date.setText(DateUtils.getRelativeTimeSpanString(ctx, timestamp)); } - private void bindIntroduction(final IntroductionHolder ui, + private void bindIntroduction(IntroductionHolder ui, final ConversationIntroductionInItem item, final int position) { final IntroductionRequest ir = item.getIntroductionRequest(); @@ -259,7 +249,7 @@ class ConversationAdapter extends RecyclerView.Adapter { } // Incoming Introduction Request (Not Answered) else { - if (item.getIntroductionRequest().doesExist()) { + if (item.getIntroductionRequest().contactExists()) { ui.text.setText(ctx.getString( R.string.introduction_request_exists_received, contactName, ir.getName())); @@ -292,8 +282,7 @@ class ConversationAdapter extends RecyclerView.Adapter { DateUtils.getRelativeTimeSpanString(ctx, item.getTime())); } - private void bindNotice(final NoticeHolder ui, - final ConversationNoticeItem item, final int position) { + private void bindNotice(NoticeHolder ui, ConversationNoticeItem item) { ui.text.setText(item.getText()); ui.date.setText( @@ -375,16 +364,10 @@ class ConversationAdapter extends RecyclerView.Adapter { } public void clear() { - this.items.beginBatchedUpdates(); - - while(items.size() != 0) { - items.removeItemAt(0); - } - - this.items.endBatchedUpdates(); + items.clear(); } - protected class MessageHolder extends RecyclerView.ViewHolder { + private static class MessageHolder extends RecyclerView.ViewHolder { public ViewGroup layout; public TextView body; @@ -408,7 +391,7 @@ class ConversationAdapter extends RecyclerView.Adapter { } } - protected class IntroductionHolder extends RecyclerView.ViewHolder { + private static class IntroductionHolder extends RecyclerView.ViewHolder { public ViewGroup layout; public View messageLayout; @@ -437,7 +420,7 @@ class ConversationAdapter extends RecyclerView.Adapter { } } - protected class NoticeHolder extends RecyclerView.ViewHolder { + private static class NoticeHolder extends RecyclerView.ViewHolder { public ViewGroup layout; public TextView text; diff --git a/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java b/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java index 66e57686a44c3a4740a823f4c23f077aa560f1fe..4fcdbdd555abf184780f2e28db7a2dc3139feec4 100644 --- a/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java +++ b/briar-android/src/org/briarproject/android/introduction/ContactChooserFragment.java @@ -103,10 +103,7 @@ public class ContactChooserFragment extends BaseFragment { @Override public void onItemClick(View view, ContactListItem item) { if (c1 == null) { - Toast.makeText(getActivity(), - R.string.introduction_error, - Toast.LENGTH_SHORT).show(); - return; + throw new RuntimeException("c1 not initialized"); } Contact c2 = item.getContact(); if (!c1.getLocalAuthorId() @@ -227,6 +224,7 @@ public class ContactChooserFragment extends BaseFragment { if (LOG.isLoggable(INFO)) LOG.info("Loading message headers took " + duration + " ms"); + now = System.currentTimeMillis(); Collection<IntroductionMessage> introductions = introductionManager .getIntroductionMessages(id); diff --git a/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java b/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java index c3905df14c91b6ad50680bf645b77fc530dd4a98..2faee1a8ab22b30d7757d91702bca976a796eb6a 100644 --- a/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java +++ b/briar-android/src/org/briarproject/android/introduction/IntroductionActivity.java @@ -27,6 +27,8 @@ public class IntroductionActivity extends BriarActivity implements Intent intent = getIntent(); contactId = intent.getIntExtra(CONTACT_ID, -1); + if (contactId == -1) + throw new IllegalArgumentException("Wrong ContactId"); setContentView(R.layout.activity_introduction); diff --git a/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java b/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java index 7646e0cf4e8710952f3650d5dfb94e7c65147efa..ed0547da4e0b9eb8b69e7c8d6ea7433ba392e0b6 100644 --- a/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java +++ b/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java @@ -1,6 +1,5 @@ package org.briarproject.android.introduction; -import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v7.app.ActionBar; @@ -37,7 +36,7 @@ public class IntroductionMessageFragment extends BaseFragment { private static final Logger LOG = Logger.getLogger(IntroductionMessageFragment.class.getName()); - public final static String TAG = "ContactChooserFragment"; + public final static String TAG = "IntroductionMessageFragment"; private IntroductionActivity introductionActivity; private ViewHolder ui; @@ -45,7 +44,6 @@ public class IntroductionMessageFragment extends BaseFragment { private final static String CONTACT_ID_2 = "contact2"; // Fields that are accessed from background threads must be volatile - private volatile boolean introductionWasMade = false; @Inject protected volatile ContactManager contactManager; @Inject @@ -129,8 +127,8 @@ public class IntroductionMessageFragment extends BaseFragment { .getContact(new ContactId(contactId2)); setUpViews(c1, c2); } catch (DbException e) { - // TODO - e.printStackTrace(); + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); } } }); @@ -167,54 +165,49 @@ public class IntroductionMessageFragment extends BaseFragment { } public void onButtonClick(final Contact c1, final Contact c2) { + // disable button to prevent accidental double invitations + ui.button.setEnabled(false); + String msg = ui.message.getText().toString(); makeIntroduction(c1, c2, msg); + + // don't wait for the introduction to be made before finishing activity + introductionActivity.hideSoftKeyboard(ui.message); + introductionActivity.finish(); } private void makeIntroduction(final Contact c1, final Contact c2, final String msg) { introductionActivity.runOnDbThread(new Runnable() { public void run() { - // prevent double introductions - if (introductionWasMade) return; - // actually make the introduction try { long timestamp = System.currentTimeMillis(); introductionManager.makeIntroduction(c1, c2, msg, timestamp); - introductionWasMade = true; - postIntroduction(false); } catch (DbException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - postIntroduction(true); + introductionError(); } catch (FormatException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - postIntroduction(true); + introductionError(); } } }); } - private void postIntroduction(final boolean error) { + private void introductionError() { introductionActivity.runOnUiThread(new Runnable() { public void run() { - introductionActivity.hideSoftKeyboard(ui.message); - if (error) { - Toast.makeText(introductionActivity, - R.string.introduction_error, Toast.LENGTH_SHORT) - .show(); - introductionActivity.setResult(Activity.RESULT_CANCELED); - } else { - introductionActivity.setResult(Activity.RESULT_OK); - } - introductionActivity.finish(); + Toast.makeText(introductionActivity, + R.string.introduction_error, Toast.LENGTH_SHORT) + .show(); } }); } - private class ViewHolder { + private static class ViewHolder { ProgressBar progressBar; ViewGroup header; CircleImageView avatar1; diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java b/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java index facd7151fbf564b1afe1f1327c3b119781416dfe..227c0500ce5b2f6cc459c87a9104407a068076b0 100644 --- a/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java +++ b/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java @@ -29,7 +29,7 @@ public class IntroductionRequest extends IntroductionResponse { return answered; } - public boolean doesExist() { + public boolean contactExists() { return exists; } diff --git a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java index dbdc0091c4dccbfc0cb5656d0c03bd62296c5e04..edec27bef53a4d1042639557c96d65f03f4bca06 100644 --- a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java +++ b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java @@ -229,7 +229,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook BdfDictionary state; try { state = getSessionState(txn, groupId, - message.getRaw(SESSION_ID, new byte[0])); + message.getRaw(SESSION_ID)); } catch (FormatException e) { LOG.warning("Could not find state for message, deleting..."); deleteMessage(txn, m.getId());