Listen for group updates, fix group updates, and Recipient marshing
This commit is contained in:
parent
86b3de2a93
commit
5000957b99
13 changed files with 119 additions and 116 deletions
|
@ -73,6 +73,8 @@ import org.thoughtcrime.securesms.mms.AttachmentTypeSelectorAdapter;
|
||||||
import org.thoughtcrime.securesms.mms.MediaTooLargeException;
|
import org.thoughtcrime.securesms.mms.MediaTooLargeException;
|
||||||
import org.thoughtcrime.securesms.mms.MmsSendHelper;
|
import org.thoughtcrime.securesms.mms.MmsSendHelper;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||||
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
|
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||||
|
@ -85,8 +87,6 @@ import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
|
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage;
|
import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||||
import org.thoughtcrime.securesms.util.ActionBarUtil;
|
import org.thoughtcrime.securesms.util.ActionBarUtil;
|
||||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||||
|
@ -116,6 +116,7 @@ import java.util.List;
|
||||||
import ws.com.google.android.mms.MmsException;
|
import ws.com.google.android.mms.MmsException;
|
||||||
|
|
||||||
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||||
|
import static org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
|
||||||
import static org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent.GroupContext;
|
import static org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent.GroupContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,6 +156,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||||
private AttachmentTypeSelectorAdapter attachmentAdapter;
|
private AttachmentTypeSelectorAdapter attachmentAdapter;
|
||||||
private AttachmentManager attachmentManager;
|
private AttachmentManager attachmentManager;
|
||||||
private BroadcastReceiver securityUpdateReceiver;
|
private BroadcastReceiver securityUpdateReceiver;
|
||||||
|
private BroadcastReceiver groupUpdateReceiver;
|
||||||
private EmojiDrawer emojiDrawer;
|
private EmojiDrawer emojiDrawer;
|
||||||
private EmojiToggle emojiToggle;
|
private EmojiToggle emojiToggle;
|
||||||
|
|
||||||
|
@ -218,6 +220,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
unregisterReceiver(securityUpdateReceiver);
|
unregisterReceiver(securityUpdateReceiver);
|
||||||
|
unregisterReceiver(groupUpdateReceiver);
|
||||||
saveDraft();
|
saveDraft();
|
||||||
MemoryCleaner.clean(masterSecret);
|
MemoryCleaner.clean(masterSecret);
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
@ -456,10 +459,10 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||||
initializeEnabledCheck();
|
initializeEnabledCheck();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
Toast.makeText(ConversationActivity.this, "Error leaving group....", Toast.LENGTH_LONG);
|
Toast.makeText(ConversationActivity.this, "Error leaving group....", Toast.LENGTH_LONG).show();
|
||||||
} catch (MmsException e) {
|
} catch (MmsException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
Toast.makeText(ConversationActivity.this, "Error leaving group...", Toast.LENGTH_LONG);
|
Toast.makeText(ConversationActivity.this, "Error leaving group...", Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -706,7 +709,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||||
|
|
||||||
private void initializeResources() {
|
private void initializeResources() {
|
||||||
recipientsPanel = (RecipientsPanel)findViewById(R.id.recipients);
|
recipientsPanel = (RecipientsPanel)findViewById(R.id.recipients);
|
||||||
recipients = getIntent().getParcelableExtra(RECIPIENTS_EXTRA);
|
recipients = RecipientFactory.getRecipientsForIds(this, getIntent().getStringExtra(RECIPIENTS_EXTRA), true);
|
||||||
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
|
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
|
||||||
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA,
|
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA,
|
||||||
ThreadDatabase.DistributionTypes.DEFAULT);
|
ThreadDatabase.DistributionTypes.DEFAULT);
|
||||||
|
@ -739,6 +742,13 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||||
emojiDrawer.setComposeEditText(composeText);
|
emojiDrawer.setComposeEditText(composeText);
|
||||||
emojiToggle.setOnClickListener(new EmojiToggleListener());
|
emojiToggle.setOnClickListener(new EmojiToggleListener());
|
||||||
|
|
||||||
|
recipients.addListener(new RecipientModifiedListener() {
|
||||||
|
@Override
|
||||||
|
public void onModified(Recipient recipient) {
|
||||||
|
initializeTitleBar();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
registerForContextMenu(sendButton);
|
registerForContextMenu(sendButton);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||||
|
@ -777,9 +787,30 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
groupUpdateReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
Log.w("ConversationActivity", "Group update received...");
|
||||||
|
if (recipients != null) {
|
||||||
|
String ids = recipients.toIdString();
|
||||||
|
Log.w("ConversationActivity", "Looking up new recipients...");
|
||||||
|
recipients = RecipientFactory.getRecipientsForIds(context, ids, true);
|
||||||
|
recipients.addListener(new RecipientModifiedListener() {
|
||||||
|
@Override
|
||||||
|
public void onModified(Recipient recipient) {
|
||||||
|
initializeTitleBar();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
registerReceiver(securityUpdateReceiver,
|
registerReceiver(securityUpdateReceiver,
|
||||||
new IntentFilter(KeyExchangeProcessor.SECURITY_UPDATE_EVENT),
|
new IntentFilter(KeyExchangeProcessor.SECURITY_UPDATE_EVENT),
|
||||||
KeyCachingService.KEY_PERMISSION, null);
|
KeyCachingService.KEY_PERMISSION, null);
|
||||||
|
|
||||||
|
registerReceiver(groupUpdateReceiver,
|
||||||
|
new IntentFilter(GroupDatabase.DATABASE_UPDATE_ACTION));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -959,7 +990,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPushGroupConversation() {
|
private boolean isPushGroupConversation() {
|
||||||
return getRecipients().isGroupRecipient();
|
return getRecipients() != null && getRecipients().isGroupRecipient();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPushDestination() {
|
private boolean isPushDestination() {
|
||||||
|
@ -967,6 +998,9 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||||
if (!TextSecurePreferences.isPushRegistered(this))
|
if (!TextSecurePreferences.isPushRegistered(this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (getRecipients() == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (isPushGroupConversation())
|
if (isPushGroupConversation())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import android.widget.CursorAdapter;
|
||||||
|
|
||||||
import com.actionbarsherlock.app.SherlockListFragment;
|
import com.actionbarsherlock.app.SherlockListFragment;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.loaders.ConversationLoader;
|
import org.thoughtcrime.securesms.database.loaders.ConversationLoader;
|
||||||
|
@ -183,9 +184,11 @@ public class ConversationFragment extends SherlockListFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeResources() {
|
private void initializeResources() {
|
||||||
|
String recipientIds = this.getActivity().getIntent().getStringExtra("recipients");
|
||||||
|
|
||||||
this.masterSecret = (MasterSecret)this.getActivity().getIntent()
|
this.masterSecret = (MasterSecret)this.getActivity().getIntent()
|
||||||
.getParcelableExtra("master_secret");
|
.getParcelableExtra("master_secret");
|
||||||
this.recipients = this.getActivity().getIntent().getParcelableExtra("recipients");
|
this.recipients = RecipientFactory.getRecipientsForIds(getActivity(), recipientIds, true);
|
||||||
this.threadId = this.getActivity().getIntent().getLongExtra("thread_id", -1);
|
this.threadId = this.getActivity().getIntent().getLongExtra("thread_id", -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
|
||||||
|
|
||||||
private void createConversation(long threadId, Recipients recipients, int distributionType) {
|
private void createConversation(long threadId, Recipients recipients, int distributionType) {
|
||||||
Intent intent = new Intent(this, ConversationActivity.class);
|
Intent intent = new Intent(this, ConversationActivity.class);
|
||||||
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients);
|
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.toIdString());
|
||||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||||
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
|
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
|
||||||
|
|
|
@ -34,12 +34,12 @@ import org.thoughtcrime.securesms.contacts.RecipientsEditor;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
|
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
|
||||||
import org.thoughtcrime.securesms.util.ActionBarUtil;
|
import org.thoughtcrime.securesms.util.ActionBarUtil;
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||||
|
@ -341,18 +341,6 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||||
new UpdateWhisperGroupAsyncTask().execute();
|
new UpdateWhisperGroupAsyncTask().execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> recipientsToNormalizedStrings(Collection<Recipient> recipients, String localNumber) {
|
|
||||||
final List<String> e164numbers = new ArrayList<String>(recipients.size());
|
|
||||||
for (Recipient contact : recipients) {
|
|
||||||
try {
|
|
||||||
e164numbers.add(PhoneNumberFormatter.formatNumber(contact.getNumber(), localNumber));
|
|
||||||
} catch (InvalidNumberException ine) {
|
|
||||||
Log.w(TAG, "Failed to format number for added group member.", ine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return e164numbers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableWhisperGroupCreatingUi() {
|
private void enableWhisperGroupCreatingUi() {
|
||||||
findViewById(R.id.group_details_layout).setVisibility(View.GONE);
|
findViewById(R.id.group_details_layout).setVisibility(View.GONE);
|
||||||
findViewById(R.id.creating_group_layout).setVisibility(View.VISIBLE);
|
findViewById(R.id.creating_group_layout).setVisibility(View.VISIBLE);
|
||||||
|
@ -428,10 +416,11 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||||
{
|
{
|
||||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(this);
|
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(this);
|
||||||
byte[] groupId = groupDatabase.allocateGroupId();
|
byte[] groupId = groupDatabase.allocateGroupId();
|
||||||
List<String> memberE164Numbers = getE164Numbers(members);
|
Set<String> memberE164Numbers = getE164Numbers(members);
|
||||||
|
|
||||||
groupDatabase.create(groupId, TextSecurePreferences.getLocalNumber(this), groupName,
|
memberE164Numbers.add(TextSecurePreferences.getLocalNumber(this));
|
||||||
memberE164Numbers, null, null);
|
|
||||||
|
groupDatabase.create(groupId, groupName, new LinkedList<String>(memberE164Numbers), null, null);
|
||||||
groupDatabase.updateAvatar(groupId, avatar);
|
groupDatabase.updateAvatar(groupId, avatar);
|
||||||
|
|
||||||
return handlePushOperation(groupId, groupName, avatar, memberE164Numbers);
|
return handlePushOperation(groupId, groupName, avatar, memberE164Numbers);
|
||||||
|
@ -442,24 +431,21 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||||
throws InvalidNumberException, MmsException
|
throws InvalidNumberException, MmsException
|
||||||
{
|
{
|
||||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(this);
|
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(this);
|
||||||
List<String> memberE164Numbers = getE164Numbers(members);
|
Set<String> memberE164Numbers = getE164Numbers(members);
|
||||||
|
memberE164Numbers.add(TextSecurePreferences.getLocalNumber(this));
|
||||||
|
|
||||||
GroupDatabase.GroupRecord record = groupDatabase.getGroup(groupId);
|
for (String number : memberE164Numbers)
|
||||||
Set<String> newMembers = new HashSet<String>(memberE164Numbers);
|
Log.w(TAG, "Updating: " + number);
|
||||||
newMembers.removeAll(record.getMembers());
|
|
||||||
|
|
||||||
groupDatabase.add(groupId, TextSecurePreferences.getLocalNumber(this),
|
|
||||||
new LinkedList<String>(newMembers));
|
|
||||||
|
|
||||||
|
groupDatabase.updateMembers(groupId, new LinkedList<String>(memberE164Numbers));
|
||||||
groupDatabase.updateTitle(groupId, groupName);
|
groupDatabase.updateTitle(groupId, groupName);
|
||||||
groupDatabase.updateAvatar(groupId, avatar);
|
groupDatabase.updateAvatar(groupId, avatar);
|
||||||
|
|
||||||
|
|
||||||
return handlePushOperation(groupId, groupName, avatar, memberE164Numbers);
|
return handlePushOperation(groupId, groupName, avatar, memberE164Numbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<Long, Recipients> handlePushOperation(byte[] groupId, String groupName, byte[] avatar,
|
private Pair<Long, Recipients> handlePushOperation(byte[] groupId, String groupName, byte[] avatar,
|
||||||
List<String> e164numbers)
|
Set<String> e164numbers)
|
||||||
throws MmsException, InvalidNumberException
|
throws MmsException, InvalidNumberException
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -501,10 +487,10 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||||
return arrayList;
|
return arrayList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getE164Numbers(Set<Recipient> recipients)
|
private Set<String> getE164Numbers(Set<Recipient> recipients)
|
||||||
throws InvalidNumberException
|
throws InvalidNumberException
|
||||||
{
|
{
|
||||||
List<String> results = new LinkedList<String>();
|
Set<String> results = new HashSet<String>();
|
||||||
|
|
||||||
for (Recipient recipient : recipients) {
|
for (Recipient recipient : recipients) {
|
||||||
results.add(Util.canonicalizeNumber(this, recipient.getNumber()));
|
results.add(Util.canonicalizeNumber(this, recipient.getNumber()));
|
||||||
|
@ -545,7 +531,7 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||||
|
|
||||||
ArrayList<Recipient> selectedContactsList = setToArrayList(selectedContacts);
|
ArrayList<Recipient> selectedContactsList = setToArrayList(selectedContacts);
|
||||||
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, new Recipients(selectedContactsList));
|
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, new Recipients(selectedContactsList).toIdString());
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
finish();
|
finish();
|
||||||
} else {
|
} else {
|
||||||
|
@ -573,7 +559,9 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||||
}
|
}
|
||||||
final String name = (groupName.getText() != null) ? groupName.getText().toString() : null;
|
final String name = (groupName.getText() != null) ? groupName.getText().toString() : null;
|
||||||
try {
|
try {
|
||||||
return handleUpdatePushGroup(groupId, name, avatarBytes, selectedContacts);
|
Set<Recipient> unionContacts = new HashSet<Recipient>(selectedContacts);
|
||||||
|
unionContacts.addAll(existingContacts);
|
||||||
|
return handleUpdatePushGroup(groupId, name, avatarBytes, unionContacts);
|
||||||
} catch (MmsException e) {
|
} catch (MmsException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
return new Pair<Long,Recipients>(RES_MMS_EXCEPTION, null);
|
return new Pair<Long,Recipients>(RES_MMS_EXCEPTION, null);
|
||||||
|
@ -638,7 +626,7 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||||
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||||
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients);
|
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.toIdString());
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
finish();
|
finish();
|
||||||
} else if (threadId == RES_BAD_NUMBER) {
|
} else if (threadId == RES_BAD_NUMBER) {
|
||||||
|
@ -671,7 +659,7 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||||
@Override
|
@Override
|
||||||
protected Boolean doInBackground(Void... voids) {
|
protected Boolean doInBackground(Void... voids) {
|
||||||
final GroupDatabase db = DatabaseFactory.getGroupDatabase(GroupCreateActivity.this);
|
final GroupDatabase db = DatabaseFactory.getGroupDatabase(GroupCreateActivity.this);
|
||||||
final Recipients recipients = db.getGroupMembers(groupId);
|
final Recipients recipients = db.getGroupMembers(groupId, false);
|
||||||
if (recipients != null) {
|
if (recipients != null) {
|
||||||
final List<Recipient> recipientList = recipients.getRecipientsList();
|
final List<Recipient> recipientList = recipients.getRecipientsList();
|
||||||
if (recipientList != null) {
|
if (recipientList != null) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class GroupMembersDialog extends AsyncTask<Void, Void, Recipients> {
|
||||||
try {
|
try {
|
||||||
String groupId = recipients.getPrimaryRecipient().getNumber();
|
String groupId = recipients.getPrimaryRecipient().getNumber();
|
||||||
return DatabaseFactory.getGroupDatabase(context)
|
return DatabaseFactory.getGroupDatabase(context)
|
||||||
.getGroupMembers(GroupUtil.getDecodedId(groupId));
|
.getGroupMembers(GroupUtil.getDecodedId(groupId), true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w("ConverstionActivity", e);
|
Log.w("ConverstionActivity", e);
|
||||||
return new Recipients(new LinkedList<Recipient>());
|
return new Recipients(new LinkedList<Recipient>());
|
||||||
|
|
|
@ -135,7 +135,7 @@ public class RoutingActivity extends PassphraseRequiredSherlockActivity {
|
||||||
|
|
||||||
private Intent getConversationIntent(ConversationParameters parameters) {
|
private Intent getConversationIntent(ConversationParameters parameters) {
|
||||||
Intent intent = new Intent(this, ConversationActivity.class);
|
Intent intent = new Intent(this, ConversationActivity.class);
|
||||||
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, parameters.recipients);
|
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, parameters.recipients != null ? parameters.recipients.toIdString() : "");
|
||||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, parameters.thread);
|
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, parameters.thread);
|
||||||
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||||
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, parameters.draftText);
|
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, parameters.draftText);
|
||||||
|
|
|
@ -113,7 +113,7 @@ public class SingleContactSelectionActivity extends PassphraseRequiredSherlockFr
|
||||||
private void openNewConversation(Recipients recipients) {
|
private void openNewConversation(Recipients recipients) {
|
||||||
if (recipients != null) {
|
if (recipients != null) {
|
||||||
Intent intent = new Intent(SingleContactSelectionActivity.this, ConversationActivity.class);
|
Intent intent = new Intent(SingleContactSelectionActivity.this, ConversationActivity.class);
|
||||||
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients);
|
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.toIdString());
|
||||||
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||||
long existingThread = DatabaseFactory.getThreadDatabase(SingleContactSelectionActivity.this).getThreadIdIfExistsFor(recipients);
|
long existingThread = DatabaseFactory.getThreadDatabase(SingleContactSelectionActivity.this).getThreadIdIfExistsFor(recipients);
|
||||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread);
|
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread);
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.database;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
@ -24,10 +25,14 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent.AttachmentPointer;
|
import static org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent.AttachmentPointer;
|
||||||
|
|
||||||
public class GroupDatabase extends Database {
|
public class GroupDatabase extends Database {
|
||||||
|
|
||||||
|
public static final String DATABASE_UPDATE_ACTION = "org.thoughtcrime.securesms.database.GroupDatabase.UPDATE";
|
||||||
|
|
||||||
private static final String TAG = GroupDatabase.class.getSimpleName();
|
private static final String TAG = GroupDatabase.class.getSimpleName();
|
||||||
|
|
||||||
private static final String TABLE_NAME = "groups";
|
private static final String TABLE_NAME = "groups";
|
||||||
|
@ -77,11 +82,15 @@ public class GroupDatabase extends Database {
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Recipients getGroupMembers(byte[] groupId) {
|
public Recipients getGroupMembers(byte[] groupId, boolean includeSelf) {
|
||||||
List<String> members = getCurrentMembers(groupId);
|
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||||
List<Recipient> recipients = new LinkedList<Recipient>();
|
List<String> members = getCurrentMembers(groupId);
|
||||||
|
List<Recipient> recipients = new LinkedList<Recipient>();
|
||||||
|
|
||||||
for (String member : members) {
|
for (String member : members) {
|
||||||
|
if (!includeSelf && member.equals(localNumber))
|
||||||
|
continue;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
recipients.addAll(RecipientFactory.getRecipientsFromString(context, member, false)
|
recipients.addAll(RecipientFactory.getRecipientsFromString(context, member, false)
|
||||||
.getRecipientsList());
|
.getRecipientsList());
|
||||||
|
@ -93,27 +102,13 @@ public class GroupDatabase extends Database {
|
||||||
return new Recipients(recipients);
|
return new Recipients(recipients);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create(byte[] groupId, String owner, String title,
|
public void create(byte[] groupId, String title, List<String> members,
|
||||||
List<String> members, AttachmentPointer avatar,
|
AttachmentPointer avatar, String relay)
|
||||||
String relay)
|
|
||||||
{
|
{
|
||||||
List<String> filteredMembers = new LinkedList<String>();
|
|
||||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
|
||||||
|
|
||||||
if (!localNumber.equals(owner)) {
|
|
||||||
filteredMembers.add(owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String member : members) {
|
|
||||||
if (!member.equals(localNumber)) {
|
|
||||||
filteredMembers.add(member);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentValues contentValues = new ContentValues();
|
ContentValues contentValues = new ContentValues();
|
||||||
contentValues.put(GROUP_ID, GroupUtil.getEncodedId(groupId));
|
contentValues.put(GROUP_ID, GroupUtil.getEncodedId(groupId));
|
||||||
contentValues.put(TITLE, title);
|
contentValues.put(TITLE, title);
|
||||||
contentValues.put(MEMBERS, Util.join(filteredMembers, ","));
|
contentValues.put(MEMBERS, Util.join(members, ","));
|
||||||
|
|
||||||
if (avatar != null) {
|
if (avatar != null) {
|
||||||
contentValues.put(AVATAR_ID, avatar.getId());
|
contentValues.put(AVATAR_ID, avatar.getId());
|
||||||
|
@ -142,7 +137,8 @@ public class GroupDatabase extends Database {
|
||||||
GROUP_ID + " = ?",
|
GROUP_ID + " = ?",
|
||||||
new String[] {GroupUtil.getEncodedId(groupId)});
|
new String[] {GroupUtil.getEncodedId(groupId)});
|
||||||
|
|
||||||
if (title != null) updateGroupRecipientTitle(groupId, title);
|
RecipientFactory.clearCache();
|
||||||
|
notifyDatabaseListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateTitle(byte[] groupId, String title) {
|
public void updateTitle(byte[] groupId, String title) {
|
||||||
|
@ -151,43 +147,32 @@ public class GroupDatabase extends Database {
|
||||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||||
new String[] {GroupUtil.getEncodedId(groupId)});
|
new String[] {GroupUtil.getEncodedId(groupId)});
|
||||||
|
|
||||||
if (title != null) updateGroupRecipientTitle(groupId, title);
|
RecipientFactory.clearCache();
|
||||||
|
notifyDatabaseListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateAvatar(byte[] groupId, Bitmap avatar) {
|
public void updateAvatar(byte[] groupId, Bitmap avatar) {
|
||||||
updateAvatarInDatabase(groupId, BitmapUtil.toByteArray(avatar));
|
updateAvatar(groupId, BitmapUtil.toByteArray(avatar));
|
||||||
updateGroupRecipientAvatar(groupId, avatar);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateAvatar(byte[] groupId, byte[] avatar) {
|
public void updateAvatar(byte[] groupId, byte[] avatar) {
|
||||||
updateAvatarInDatabase(groupId, avatar);
|
|
||||||
updateGroupRecipientAvatar(groupId, BitmapFactory.decodeByteArray(avatar, 0, avatar.length));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateAvatarInDatabase(byte[] groupId, byte[] avatar) {
|
|
||||||
ContentValues contentValues = new ContentValues();
|
ContentValues contentValues = new ContentValues();
|
||||||
contentValues.put(AVATAR, avatar);
|
contentValues.put(AVATAR, avatar);
|
||||||
|
|
||||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||||
new String[] {GroupUtil.getEncodedId(groupId)});
|
new String[] {GroupUtil.getEncodedId(groupId)});
|
||||||
|
|
||||||
|
RecipientFactory.clearCache();
|
||||||
|
notifyDatabaseListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(byte[] id, String source, List<String> members) {
|
public void updateMembers(byte[] id, List<String> members) {
|
||||||
List<String> currentMembers = getCurrentMembers(id);
|
ContentValues contents = new ContentValues();
|
||||||
|
contents.put(MEMBERS, Util.join(members, ","));
|
||||||
|
contents.put(ACTIVE, 1);
|
||||||
|
|
||||||
for (String currentMember : currentMembers) {
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||||
if (currentMember.equals(source)) {
|
new String[] {GroupUtil.getEncodedId(id)});
|
||||||
List<String> concatenatedMembers = new LinkedList<String>(currentMembers);
|
|
||||||
concatenatedMembers.addAll(members);
|
|
||||||
|
|
||||||
ContentValues contents = new ContentValues();
|
|
||||||
contents.put(MEMBERS, Util.join(concatenatedMembers, ","));
|
|
||||||
contents.put(ACTIVE, 1);
|
|
||||||
|
|
||||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
|
||||||
new String[] {GroupUtil.getEncodedId(id)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(byte[] id, String source) {
|
public void remove(byte[] id, String source) {
|
||||||
|
@ -198,7 +183,7 @@ public class GroupDatabase extends Database {
|
||||||
contents.put(MEMBERS, Util.join(currentMembers, ","));
|
contents.put(MEMBERS, Util.join(currentMembers, ","));
|
||||||
|
|
||||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||||
new String[]{GroupUtil.getEncodedId(id)});
|
new String[] {GroupUtil.getEncodedId(id)});
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getCurrentMembers(byte[] id) {
|
private List<String> getCurrentMembers(byte[] id) {
|
||||||
|
@ -244,6 +229,10 @@ public class GroupDatabase extends Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifyDatabaseListeners() {
|
||||||
|
Intent intent = new Intent(DATABASE_UPDATE_ACTION);
|
||||||
|
context.sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
|
||||||
public static class Reader {
|
public static class Reader {
|
||||||
|
|
||||||
|
@ -342,28 +331,4 @@ public class GroupDatabase extends Database {
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Recipient getGroupRecipient(byte[] groupId) {
|
|
||||||
try {
|
|
||||||
return RecipientFactory.getRecipientsFromString(context, GroupUtil.getEncodedId(groupId), true)
|
|
||||||
.getPrimaryRecipient();
|
|
||||||
} catch (RecipientFormattingException e) {
|
|
||||||
Log.w(TAG, e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateGroupRecipientTitle(byte[] groupId, String title) {
|
|
||||||
Recipient groupRecipient = getGroupRecipient(groupId);
|
|
||||||
Log.i(TAG, "updating group recipient title for recipient " + System.identityHashCode(groupRecipient));
|
|
||||||
if (groupRecipient != null) groupRecipient.setName(title);
|
|
||||||
else Log.w(TAG, "Couldn't update group title because recipient couldn't be found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateGroupRecipientAvatar(byte[] groupId, Bitmap photo) {
|
|
||||||
Recipient groupRecipient = getGroupRecipient(groupId);
|
|
||||||
if (groupRecipient != null) groupRecipient.setContactPhoto(photo);
|
|
||||||
else Log.w(TAG, "Couldn't update group title because recipient couldn't be found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,9 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SpannableString getDisplayBody() {
|
public SpannableString getDisplayBody() {
|
||||||
if (isGroupUpdate()) {
|
if (isGroupUpdate() && isOutgoing()) {
|
||||||
|
return emphasisAdded("Updated the group.");
|
||||||
|
} else if (isGroupUpdate()) {
|
||||||
return emphasisAdded(GroupUtil.getDescription(getBody().getBody()));
|
return emphasisAdded(GroupUtil.getDescription(getBody().getBody()));
|
||||||
} else if (isGroupQuit() && isOutgoing()) {
|
} else if (isGroupQuit() && isOutgoing()) {
|
||||||
return emphasisAdded("You have left the group.");
|
return emphasisAdded("You have left the group.");
|
||||||
|
|
|
@ -23,6 +23,7 @@ import android.util.Patterns;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
|
import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
|
||||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||||
import org.thoughtcrime.securesms.util.NumberUtil;
|
import org.thoughtcrime.securesms.util.NumberUtil;
|
||||||
|
import org.whispersystems.textsecure.util.Util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -137,6 +138,16 @@ public class Recipients implements Parcelable {
|
||||||
return this.recipients;
|
return this.recipients;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toIdString() {
|
||||||
|
List<String> ids = new LinkedList<String>();
|
||||||
|
|
||||||
|
for (Recipient recipient : recipients) {
|
||||||
|
ids.add(String.valueOf(recipient.getRecipientId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Util.join(ids, " ");
|
||||||
|
}
|
||||||
|
|
||||||
public String[] toNumberStringArray(boolean scrub) {
|
public String[] toNumberStringArray(boolean scrub) {
|
||||||
String[] recipientsArray = new String[recipients.size()];
|
String[] recipientsArray = new String[recipients.size()];
|
||||||
Iterator<Recipient> iterator = recipients.iterator();
|
Iterator<Recipient> iterator = recipients.iterator();
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class GroupReceiver {
|
||||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||||
byte[] id = group.getId().toByteArray();
|
byte[] id = group.getId().toByteArray();
|
||||||
|
|
||||||
database.create(id, message.getSource(), group.getName(), group.getMembersList(),
|
database.create(id, group.getName(), group.getMembersList(),
|
||||||
group.getAvatar(), message.getRelay());
|
group.getAvatar(), message.getRelay());
|
||||||
|
|
||||||
storeMessage(masterSecret, message, group);
|
storeMessage(masterSecret, message, group);
|
||||||
|
@ -98,7 +98,7 @@ public class GroupReceiver {
|
||||||
if (addedMembers.size() > 0) {
|
if (addedMembers.size() > 0) {
|
||||||
Set<String> unionMembers = new HashSet<String>(recordMembers);
|
Set<String> unionMembers = new HashSet<String>(recordMembers);
|
||||||
unionMembers.addAll(messageMembers);
|
unionMembers.addAll(messageMembers);
|
||||||
database.add(id, message.getSource(), new LinkedList<String>(unionMembers));
|
database.updateMembers(id, new LinkedList<String>(unionMembers));
|
||||||
|
|
||||||
group = group.toBuilder().clearMembers().addAllMembers(addedMembers).build();
|
group = group.toBuilder().clearMembers().addAllMembers(addedMembers).build();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -115,7 +115,7 @@ public class PushTransport extends BaseTransport {
|
||||||
|
|
||||||
if (GroupUtil.isEncodedGroup(destination)) {
|
if (GroupUtil.isEncodedGroup(destination)) {
|
||||||
recipients = DatabaseFactory.getGroupDatabase(context)
|
recipients = DatabaseFactory.getGroupDatabase(context)
|
||||||
.getGroupMembers(GroupUtil.getDecodedId(destination));
|
.getGroupMembers(GroupUtil.getDecodedId(destination), false);
|
||||||
} else {
|
} else {
|
||||||
recipients = RecipientFactory.getRecipientsFromString(context, destination, false);
|
recipients = RecipientFactory.getRecipientsFromString(context, destination, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class GroupUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title != null && !title.trim().isEmpty()) {
|
if (title != null && !title.trim().isEmpty()) {
|
||||||
description += " Updated title to '" + title + "'.";
|
description += " Title is now '" + title + "'.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return description;
|
return description;
|
||||||
|
|
Loading…
Add table
Reference in a new issue