mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-23 03:06:20 +00:00
Add the ability to block groups.
This also fixes the situation where we block group-leave messages, preventing blocked contacts from leaving groups. Fixes #7970 Also, this forced us to upgrade libsignal-service, which fixes the websocket timeout issues. Thanks to @dpapavas! Fixes #6644
This commit is contained in:
@@ -51,6 +51,8 @@ import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.KeyEvent;
|
||||
@@ -70,7 +72,6 @@ import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.gms.location.places.ui.PlacePicker;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
@@ -192,7 +193,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import static org.thoughtcrime.securesms.TransportOption.Type;
|
||||
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import static org.whispersystems.libsignal.SessionCipher.SESSION_LOCK;
|
||||
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
|
||||
/**
|
||||
* Activity for displaying a message thread, as well as
|
||||
@@ -693,26 +693,34 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void handleUnblock() {
|
||||
int titleRes = R.string.ConversationActivity_unblock_this_contact_question;
|
||||
int bodyRes = R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact;
|
||||
|
||||
if (recipient.isGroupRecipient()) {
|
||||
titleRes = R.string.ConversationActivity_unblock_this_group_question;
|
||||
bodyRes = R.string.ConversationActivity_unblock_this_group_description;
|
||||
}
|
||||
|
||||
//noinspection CodeBlock2Expr
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.ConversationActivity_unblock_this_contact_question)
|
||||
.setMessage(R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ConversationActivity_unblock, (dialog, which) -> {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
||||
.setTitle(titleRes)
|
||||
.setMessage(bodyRes)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ConversationActivity_unblock, (dialog, which) -> {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
||||
.setBlocked(recipient, false);
|
||||
|
||||
ApplicationContext.getInstance(ConversationActivity.this)
|
||||
.getJobManager()
|
||||
.add(new MultiDeviceBlockedUpdateJob(ConversationActivity.this));
|
||||
ApplicationContext.getInstance(ConversationActivity.this)
|
||||
.getJobManager()
|
||||
.add(new MultiDeviceBlockedUpdateJob(ConversationActivity.this));
|
||||
|
||||
return null;
|
||||
}
|
||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}).show();
|
||||
return null;
|
||||
}
|
||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}).show();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
@@ -847,24 +855,21 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
builder.setCancelable(true);
|
||||
builder.setMessage(getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group));
|
||||
builder.setPositiveButton(R.string.yes, (dialog, which) -> {
|
||||
Context self = ConversationActivity.this;
|
||||
Recipient groupRecipient = getRecipient();
|
||||
long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdFor(groupRecipient);
|
||||
Optional<OutgoingGroupMediaMessage> leaveMessage = GroupUtil.createGroupLeaveMessage(this, groupRecipient);
|
||||
|
||||
try {
|
||||
String groupId = getRecipient().getAddress().toGroupString();
|
||||
DatabaseFactory.getGroupDatabase(self).setActive(groupId, false);
|
||||
if (threadId != -1 && leaveMessage.isPresent()) {
|
||||
MessageSender.send(this, leaveMessage.get(), threadId, false, null);
|
||||
|
||||
GroupContext context = GroupContext.newBuilder()
|
||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
|
||||
.setType(GroupContext.Type.QUIT)
|
||||
.build();
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(this);
|
||||
String groupId = groupRecipient.getAddress().toGroupString();
|
||||
groupDatabase.setActive(groupId, false);
|
||||
groupDatabase.remove(groupId, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)));
|
||||
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(getRecipient(), context, null, System.currentTimeMillis(), 0, null, Collections.emptyList());
|
||||
MessageSender.send(self, outgoingMessage, threadId, false, null);
|
||||
DatabaseFactory.getGroupDatabase(self).remove(groupId, Address.fromSerialized(TextSecurePreferences.getLocalNumber(self)));
|
||||
initializeEnabledCheck();
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
Toast.makeText(self, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(this, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
@@ -30,6 +29,7 @@ import android.support.v7.widget.Toolbar;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.MenuItem;
|
||||
@@ -37,6 +37,7 @@ import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
@@ -55,6 +56,7 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.preferences.CorrectedPreferenceFragment;
|
||||
@@ -62,11 +64,13 @@ import org.thoughtcrime.securesms.preferences.widgets.ColorPickerPreference;
|
||||
import org.thoughtcrime.securesms.preferences.widgets.ContactPreference;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
@@ -378,10 +382,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
|
||||
if (recipient.isGroupRecipient()) {
|
||||
if (colorPreference != null) colorPreference.setVisible(false);
|
||||
if (blockPreference != null) blockPreference.setVisible(false);
|
||||
if (identityPreference != null) identityPreference.setVisible(false);
|
||||
if (privacyCategory != null) privacyCategory.setVisible(false);
|
||||
if (divider != null) divider.setVisible(false);
|
||||
if (aboutCategory != null) getPreferenceScreen().removePreference(aboutCategory);
|
||||
if (aboutDivider != null) getPreferenceScreen().removePreference(aboutDivider);
|
||||
} else {
|
||||
@@ -659,31 +660,55 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
}
|
||||
|
||||
private void handleBlock() {
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.RecipientPreferenceActivity_block_this_contact_question)
|
||||
.setMessage(R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact)
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.RecipientPreferenceActivity_block, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
setBlocked(recipient, true);
|
||||
new AsyncTask<Void, Void, Pair<Integer, Integer>>() {
|
||||
|
||||
@Override
|
||||
protected Pair<Integer, Integer> doInBackground(Void... voids) {
|
||||
int titleRes = R.string.RecipientPreferenceActivity_block_this_contact_question;
|
||||
int bodyRes = R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact;
|
||||
|
||||
if (recipient.isGroupRecipient()) {
|
||||
bodyRes = R.string.RecipientPreferenceActivity_block_and_leave_group_description;
|
||||
|
||||
if (recipient.isGroupRecipient() && DatabaseFactory.getGroupDatabase(getContext()).isActive(recipient.getAddress().toGroupString())) {
|
||||
titleRes = R.string.RecipientPreferenceActivity_block_and_leave_group;
|
||||
} else {
|
||||
titleRes = R.string.RecipientPreferenceActivity_block_group;
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
return new Pair<>(titleRes, bodyRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Pair<Integer, Integer> titleAndBody) {
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle(titleAndBody.first)
|
||||
.setMessage(titleAndBody.second)
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.RecipientPreferenceActivity_block, (dialog, which) -> {
|
||||
setBlocked(recipient, true);
|
||||
}).show();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void handleUnblock() {
|
||||
int titleRes = R.string.RecipientPreferenceActivity_unblock_this_contact_question;
|
||||
int bodyRes = R.string.RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact;
|
||||
|
||||
if (recipient.isGroupRecipient()) {
|
||||
titleRes = R.string.RecipientPreferenceActivity_unblock_this_group_question;
|
||||
bodyRes = R.string.RecipientPreferenceActivity_unblock_this_group_description;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.RecipientPreferenceActivity_unblock_this_contact_question)
|
||||
.setMessage(R.string.RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
setBlocked(recipient, false);
|
||||
}
|
||||
}).show();
|
||||
.setTitle(titleRes)
|
||||
.setMessage(bodyRes)
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock, (dialog, which) -> setBlocked(recipient, false)).show();
|
||||
}
|
||||
|
||||
private void setBlocked(final Recipient recipient, final boolean blocked) {
|
||||
@@ -695,6 +720,23 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
DatabaseFactory.getRecipientDatabase(context)
|
||||
.setBlocked(recipient, blocked);
|
||||
|
||||
if (recipient.isGroupRecipient() && DatabaseFactory.getGroupDatabase(context).isActive(recipient.getAddress().toGroupString())) {
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
Optional<OutgoingGroupMediaMessage> leaveMessage = GroupUtil.createGroupLeaveMessage(context, recipient);
|
||||
|
||||
if (threadId != -1 && leaveMessage.isPresent()) {
|
||||
MessageSender.send(context, leaveMessage.get(), threadId, false, null);
|
||||
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
String groupId = recipient.getAddress().toGroupString();
|
||||
groupDatabase.setActive(groupId, false);
|
||||
groupDatabase.remove(groupId, Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||
} else {
|
||||
Log.w(TAG, "Failed to leave group. Can't block.");
|
||||
Toast.makeText(context, R.string.RecipientPreferenceActivity_error_leaving_group, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationContext.getInstance(context)
|
||||
.getJobManager()
|
||||
.add(new MultiDeviceBlockedUpdateJob(context));
|
||||
|
||||
@@ -44,6 +44,9 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
||||
import org.whispersystems.signalservice.api.util.RealtimeSleepTimer;
|
||||
import org.whispersystems.signalservice.api.util.SleepTimer;
|
||||
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||
import org.whispersystems.signalservice.api.websocket.ConnectivityListener;
|
||||
|
||||
import dagger.Module;
|
||||
@@ -124,10 +127,13 @@ public class SignalCommunicationModule {
|
||||
@Provides
|
||||
synchronized SignalServiceMessageReceiver provideSignalMessageReceiver() {
|
||||
if (this.messageReceiver == null) {
|
||||
SleepTimer sleepTimer = TextSecurePreferences.isGcmDisabled(context) ? new RealtimeSleepTimer(context) : new UptimeSleepTimer();
|
||||
|
||||
this.messageReceiver = new SignalServiceMessageReceiver(networkAccess.getConfiguration(context),
|
||||
new DynamicCredentialsProvider(context),
|
||||
BuildConfig.USER_AGENT,
|
||||
new PipeConnectivityListener());
|
||||
new PipeConnectivityListener(),
|
||||
sleepTimer);
|
||||
}
|
||||
|
||||
return this.messageReceiver;
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
||||
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage;
|
||||
@@ -47,17 +48,20 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje
|
||||
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
|
||||
|
||||
try (RecipientReader reader = database.readerForBlocked(database.getBlocked())) {
|
||||
List<String> blocked = new LinkedList<>();
|
||||
List<String> blockedIndividuals = new LinkedList<>();
|
||||
List<byte[]> blockedGroups = new LinkedList<>();
|
||||
|
||||
Recipient recipient;
|
||||
|
||||
while ((recipient = reader.getNext()) != null) {
|
||||
if (!recipient.isGroupRecipient()) {
|
||||
blocked.add(recipient.getAddress().serialize());
|
||||
if (recipient.isGroupRecipient()) {
|
||||
blockedGroups.add(GroupUtil.getDecodedId(recipient.getAddress().toGroupString()));
|
||||
} else {
|
||||
blockedIndividuals.add(recipient.getAddress().serialize());
|
||||
}
|
||||
}
|
||||
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(blocked)));
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(blockedIndividuals, blockedGroups)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,9 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject
|
||||
|
||||
out.write(new DeviceGroup(record.getId(), Optional.fromNullable(record.getTitle()),
|
||||
members, getAvatar(record.getAvatar()),
|
||||
record.isActive(), expirationTimer));
|
||||
record.isActive(), expirationTimer,
|
||||
Optional.of(recipient.getColor().serialize()),
|
||||
recipient.isBlocked()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -175,6 +175,11 @@ public class PushDecryptJob extends ContextJob {
|
||||
|
||||
SignalServiceContent content = cipher.decrypt(envelope);
|
||||
|
||||
if (shouldIgnore(envelope, content)) {
|
||||
Log.i(TAG, "Ignoring message.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (content.getDataMessage().isPresent()) {
|
||||
SignalServiceDataMessage message = content.getDataMessage().get();
|
||||
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent();
|
||||
@@ -941,4 +946,36 @@ public class PushDecryptJob extends ContextJob {
|
||||
return Recipient.from(context, Address.fromExternal(context, envelope.getSource()), false);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldIgnore(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
|
||||
Recipient sender = Recipient.from(context, Address.fromExternal(context, envelope.getSource()), false);
|
||||
|
||||
if (content.getDataMessage().isPresent()) {
|
||||
SignalServiceDataMessage message = content.getDataMessage().get();
|
||||
Recipient conversation = getMessageDestination(envelope, message);
|
||||
|
||||
if (conversation.isGroupRecipient() && conversation.isBlocked()) {
|
||||
return true;
|
||||
} else if (conversation.isGroupRecipient()) {
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
Optional<String> groupId = message.getGroupInfo().isPresent() ? Optional.of(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false))
|
||||
: Optional.absent();
|
||||
|
||||
boolean isTextMessage = message.getBody().isPresent();
|
||||
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent();
|
||||
boolean isExpireMessage = message.isExpirationUpdate();
|
||||
boolean isContentMessage = !message.isGroupUpdate() && (isTextMessage || isMediaMessage || isExpireMessage);
|
||||
boolean isGroupActive = groupId.isPresent() && groupDatabase.isActive(groupId.get());
|
||||
boolean isLeaveMessage = message.getGroupInfo().isPresent() && message.getGroupInfo().get().getType() == SignalServiceGroup.Type.QUIT;
|
||||
|
||||
return (isContentMessage && !isGroupActive) || (sender.isBlocked() && !isLeaveMessage);
|
||||
} else {
|
||||
return sender.isBlocked();
|
||||
}
|
||||
} else if (content.getCallMessage().isPresent()) {
|
||||
return sender.isBlocked();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,22 +34,17 @@ public abstract class PushReceivedJob extends ContextJob {
|
||||
if (envelope.isReceipt()) {
|
||||
handleReceipt(envelope);
|
||||
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage()) {
|
||||
handleMessage(envelope, source);
|
||||
handleMessage(envelope);
|
||||
} else {
|
||||
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMessage(SignalServiceEnvelope envelope, Address source) {
|
||||
Recipient recipients = Recipient.from(context, source, false);
|
||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
|
||||
if (!recipients.isBlocked()) {
|
||||
long messageId = DatabaseFactory.getPushDatabase(context).insert(envelope);
|
||||
jobManager.add(new PushDecryptJob(context, messageId));
|
||||
} else {
|
||||
Log.w(TAG, "*** Received blocked push message, ignoring...");
|
||||
}
|
||||
private void handleMessage(SignalServiceEnvelope envelope) {
|
||||
long messageId = DatabaseFactory.getPushDatabase(context).insert(envelope);
|
||||
ApplicationContext.getInstance(context)
|
||||
.getJobManager()
|
||||
.add(new PushDecryptJob(context, messageId));
|
||||
}
|
||||
|
||||
private void handleReceipt(SignalServiceEnvelope envelope) {
|
||||
|
||||
@@ -3,14 +3,23 @@ package org.thoughtcrime.securesms.util;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.WorkerThread;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -20,7 +29,7 @@ public class GroupUtil {
|
||||
|
||||
private static final String ENCODED_SIGNAL_GROUP_PREFIX = "__textsecure_group__!";
|
||||
private static final String ENCODED_MMS_GROUP_PREFIX = "__signal_mms_group__!";
|
||||
private static final String TAG = GroupUtil.class.getSimpleName();
|
||||
private static final String TAG = GroupUtil.class.getSimpleName();
|
||||
|
||||
public static String getEncodedId(byte[] groupId, boolean mms) {
|
||||
return (mms ? ENCODED_MMS_GROUP_PREFIX : ENCODED_SIGNAL_GROUP_PREFIX) + Hex.toStringCondensed(groupId);
|
||||
@@ -42,6 +51,33 @@ public class GroupUtil {
|
||||
return groupId.startsWith(ENCODED_MMS_GROUP_PREFIX);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public static Optional<OutgoingGroupMediaMessage> createGroupLeaveMessage(@NonNull Context context, @NonNull Recipient groupRecipient) {
|
||||
String encodedGroupId = groupRecipient.getAddress().toGroupString();
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
|
||||
if (!groupDatabase.isActive(encodedGroupId)) {
|
||||
Log.w(TAG, "Group has already been left.");
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
ByteString decodedGroupId;
|
||||
try {
|
||||
decodedGroupId = ByteString.copyFrom(getDecodedId(encodedGroupId));
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Failed to decode group ID.", e);
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
GroupContext groupContext = GroupContext.newBuilder()
|
||||
.setId(decodedGroupId)
|
||||
.setType(GroupContext.Type.QUIT)
|
||||
.build();
|
||||
|
||||
return Optional.of(new OutgoingGroupMediaMessage(groupRecipient, groupContext, null, System.currentTimeMillis(), 0, null, Collections.emptyList()));
|
||||
}
|
||||
|
||||
|
||||
public static @NonNull GroupDescription getDescription(@NonNull Context context, @Nullable String encodedGroup) {
|
||||
if (encodedGroup == null) {
|
||||
return new GroupDescription(context, null);
|
||||
|
||||
Reference in New Issue
Block a user