mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-23 00:17:34 +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:
parent
741b775d3e
commit
45c4eafbd7
@ -77,7 +77,7 @@ dependencies {
|
|||||||
compile 'com.google.android.exoplayer:exoplayer-core:2.8.4'
|
compile 'com.google.android.exoplayer:exoplayer-core:2.8.4'
|
||||||
compile 'com.google.android.exoplayer:exoplayer-ui:2.8.4'
|
compile 'com.google.android.exoplayer:exoplayer-ui:2.8.4'
|
||||||
|
|
||||||
compile 'org.whispersystems:signal-service-android:2.7.6'
|
compile 'org.whispersystems:signal-service-android:2.8.1'
|
||||||
compile 'org.whispersystems:webrtc-android:M69'
|
compile 'org.whispersystems:webrtc-android:M69'
|
||||||
|
|
||||||
compile "me.leolin:ShortcutBadger:1.1.16"
|
compile "me.leolin:ShortcutBadger:1.1.16"
|
||||||
@ -171,7 +171,7 @@ dependencyVerification {
|
|||||||
'com.google.android.gms:play-services-maps:45e8021e7ddac4a44a82a0e9698991389ded3023d35c58f38dbd86d54211ec0e',
|
'com.google.android.gms:play-services-maps:45e8021e7ddac4a44a82a0e9698991389ded3023d35c58f38dbd86d54211ec0e',
|
||||||
'com.google.android.exoplayer:exoplayer-ui:027557b2d69b15e1852a2530b36971f0dcc177abae240ee35e05f63502cdb0a7',
|
'com.google.android.exoplayer:exoplayer-ui:027557b2d69b15e1852a2530b36971f0dcc177abae240ee35e05f63502cdb0a7',
|
||||||
'com.google.android.exoplayer:exoplayer-core:e69b409e11887c955deb373357c30eeabf183395db0092b4817e0f80bb467d5b',
|
'com.google.android.exoplayer:exoplayer-core:e69b409e11887c955deb373357c30eeabf183395db0092b4817e0f80bb467d5b',
|
||||||
'org.whispersystems:signal-service-android:823eed29e64fb0aa30d2078cb5ec0245e2a0713a4028121329c5c28788ef27f8',
|
'org.whispersystems:signal-service-android:414e91598abd941eb3be9a85702538cc9928d8c22f00e07716b83a096cbbe54d',
|
||||||
'org.whispersystems:webrtc-android:5493c92141ce884fc5ce8240d783232f4fe14bd17a8d0d7d1bd4944d0bd1682f',
|
'org.whispersystems:webrtc-android:5493c92141ce884fc5ce8240d783232f4fe14bd17a8d0d7d1bd4944d0bd1682f',
|
||||||
'me.leolin:ShortcutBadger:e3cb3e7625892129b0c92dd5e4bc649faffdd526d5af26d9c45ee31ff8851774',
|
'me.leolin:ShortcutBadger:e3cb3e7625892129b0c92dd5e4bc649faffdd526d5af26d9c45ee31ff8851774',
|
||||||
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
|
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
|
||||||
@ -218,7 +218,7 @@ dependencyVerification {
|
|||||||
'com.github.bumptech.glide:gifdecoder:59ccf3bb0cec11dab4b857382cbe0b171111b6fc62bf141adce4e1180889af15',
|
'com.github.bumptech.glide:gifdecoder:59ccf3bb0cec11dab4b857382cbe0b171111b6fc62bf141adce4e1180889af15',
|
||||||
'com.android.support:support-annotations:af05330d997eb92a066534dbe0a3ea24347d26d7001221092113ae02a8f233da',
|
'com.android.support:support-annotations:af05330d997eb92a066534dbe0a3ea24347d26d7001221092113ae02a8f233da',
|
||||||
'org.whispersystems:signal-protocol-android:5b8acded7f2a40178eb90ab8e8cbfec89d170d91b3ff5e78487d1098df6185a1',
|
'org.whispersystems:signal-protocol-android:5b8acded7f2a40178eb90ab8e8cbfec89d170d91b3ff5e78487d1098df6185a1',
|
||||||
'org.whispersystems:signal-service-java:6169643c65dcba8c784744006fc3afd9b6f309041b310a33a624121e3577433a',
|
'org.whispersystems:signal-service-java:c7ab92374e9656ba86a8d859cec71d03a68bba3e7ec0b7c597b726bf720eac21',
|
||||||
'com.github.bumptech.glide:disklrucache:c1b1b6f5bbd01e2fcdc9d7f60913c8d338bdb65ed4a93bfa02b56f19daaade4b',
|
'com.github.bumptech.glide:disklrucache:c1b1b6f5bbd01e2fcdc9d7f60913c8d338bdb65ed4a93bfa02b56f19daaade4b',
|
||||||
'com.github.bumptech.glide:annotations:bede99ef9f71517a4274bac18fd3e483e9f2b6108d7d6fe8f4949be4aa4d9512',
|
'com.github.bumptech.glide:annotations:bede99ef9f71517a4274bac18fd3e483e9f2b6108d7d6fe8f4949be4aa4d9512',
|
||||||
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
|
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
|
||||||
|
@ -148,7 +148,9 @@
|
|||||||
<string name="ConversationActivity_error_leaving_group">Error leaving group</string>
|
<string name="ConversationActivity_error_leaving_group">Error leaving group</string>
|
||||||
<string name="ConversationActivity_specify_recipient">Please choose a contact</string>
|
<string name="ConversationActivity_specify_recipient">Please choose a contact</string>
|
||||||
<string name="ConversationActivity_unblock_this_contact_question">Unblock this contact?</string>
|
<string name="ConversationActivity_unblock_this_contact_question">Unblock this contact?</string>
|
||||||
|
<string name="ConversationActivity_unblock_this_group_question">Unblock this group?</string>
|
||||||
<string name="ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact">You will once again be able to receive messages and calls from this contact.</string>
|
<string name="ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact">You will once again be able to receive messages and calls from this contact.</string>
|
||||||
|
<string name="ConversationActivity_unblock_this_group_description">Existing members will be able to add you to the group again.</string>
|
||||||
<string name="ConversationActivity_unblock">Unblock</string>
|
<string name="ConversationActivity_unblock">Unblock</string>
|
||||||
<string name="ConversationActivity_attachment_exceeds_size_limits">Attachment exceeds size limits for the type of message you\'re sending.</string>
|
<string name="ConversationActivity_attachment_exceeds_size_limits">Attachment exceeds size limits for the type of message you\'re sending.</string>
|
||||||
<string name="ConversationActivity_quick_camera_unavailable">Camera unavailable</string>
|
<string name="ConversationActivity_quick_camera_unavailable">Camera unavailable</string>
|
||||||
@ -479,9 +481,15 @@
|
|||||||
<!-- RecipientPreferencesActivity -->
|
<!-- RecipientPreferencesActivity -->
|
||||||
<string name="RecipientPreferenceActivity_block_this_contact_question">Block this contact?</string>
|
<string name="RecipientPreferenceActivity_block_this_contact_question">Block this contact?</string>
|
||||||
<string name="RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact">You will no longer receive messages and calls from this contact.</string>
|
<string name="RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact">You will no longer receive messages and calls from this contact.</string>
|
||||||
|
<string name="RecipientPreferenceActivity_block_and_leave_group">Block and leave this group?</string>
|
||||||
|
<string name="RecipientPreferenceActivity_block_group">Block this group?</string>
|
||||||
|
<string name="RecipientPreferenceActivity_block_and_leave_group_description">You will no longer receive messages or updates from this group.</string>
|
||||||
<string name="RecipientPreferenceActivity_block">Block</string>
|
<string name="RecipientPreferenceActivity_block">Block</string>
|
||||||
<string name="RecipientPreferenceActivity_unblock_this_contact_question">Unblock this contact?</string>
|
<string name="RecipientPreferenceActivity_unblock_this_contact_question">Unblock this contact?</string>
|
||||||
<string name="RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact">You will once again be able to receive messages and calls from this contact.</string>
|
<string name="RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact">You will once again be able to receive messages and calls from this contact.</string>
|
||||||
|
<string name="RecipientPreferenceActivity_unblock_this_group_question">Unblock this group?</string>
|
||||||
|
<string name="RecipientPreferenceActivity_unblock_this_group_description">Existing members will be able to add you to the group again.</string>
|
||||||
|
<string name="RecipientPreferenceActivity_error_leaving_group">Error leaving group</string>
|
||||||
<string name="RecipientPreferenceActivity_unblock">Unblock</string>
|
<string name="RecipientPreferenceActivity_unblock">Unblock</string>
|
||||||
<string name="RecipientPreferenceActivity_enabled">Enabled</string>
|
<string name="RecipientPreferenceActivity_enabled">Enabled</string>
|
||||||
<string name="RecipientPreferenceActivity_disabled">Disabled</string>
|
<string name="RecipientPreferenceActivity_disabled">Disabled</string>
|
||||||
|
@ -51,6 +51,8 @@ import android.support.v7.app.AlertDialog;
|
|||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
@ -70,7 +72,6 @@ import android.widget.TextView;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.google.android.gms.location.places.ui.PlacePicker;
|
import com.google.android.gms.location.places.ui.PlacePicker;
|
||||||
import com.google.protobuf.ByteString;
|
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
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.TransportOption.Type;
|
||||||
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||||
import static org.whispersystems.libsignal.SessionCipher.SESSION_LOCK;
|
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
|
* Activity for displaying a message thread, as well as
|
||||||
@ -693,26 +693,34 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleUnblock() {
|
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
|
//noinspection CodeBlock2Expr
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.ConversationActivity_unblock_this_contact_question)
|
.setTitle(titleRes)
|
||||||
.setMessage(R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
|
.setMessage(bodyRes)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.ConversationActivity_unblock, (dialog, which) -> {
|
.setPositiveButton(R.string.ConversationActivity_unblock, (dialog, which) -> {
|
||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
||||||
.setBlocked(recipient, false);
|
.setBlocked(recipient, false);
|
||||||
|
|
||||||
ApplicationContext.getInstance(ConversationActivity.this)
|
ApplicationContext.getInstance(ConversationActivity.this)
|
||||||
.getJobManager()
|
.getJobManager()
|
||||||
.add(new MultiDeviceBlockedUpdateJob(ConversationActivity.this));
|
.add(new MultiDeviceBlockedUpdateJob(ConversationActivity.this));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}).show();
|
}).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||||
@ -847,24 +855,21 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
builder.setCancelable(true);
|
builder.setCancelable(true);
|
||||||
builder.setMessage(getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group));
|
builder.setMessage(getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group));
|
||||||
builder.setPositiveButton(R.string.yes, (dialog, which) -> {
|
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 {
|
if (threadId != -1 && leaveMessage.isPresent()) {
|
||||||
String groupId = getRecipient().getAddress().toGroupString();
|
MessageSender.send(this, leaveMessage.get(), threadId, false, null);
|
||||||
DatabaseFactory.getGroupDatabase(self).setActive(groupId, false);
|
|
||||||
|
|
||||||
GroupContext context = GroupContext.newBuilder()
|
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(this);
|
||||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
|
String groupId = groupRecipient.getAddress().toGroupString();
|
||||||
.setType(GroupContext.Type.QUIT)
|
groupDatabase.setActive(groupId, false);
|
||||||
.build();
|
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();
|
initializeEnabledCheck();
|
||||||
} catch (IOException e) {
|
} else {
|
||||||
Log.w(TAG, e);
|
Toast.makeText(this, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
|
||||||
Toast.makeText(self, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package org.thoughtcrime.securesms;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
@ -30,6 +29,7 @@ import android.support.v7.widget.Toolbar;
|
|||||||
import android.telephony.PhoneNumberUtils;
|
import android.telephony.PhoneNumberUtils;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
||||||
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -37,6 +37,7 @@ import android.view.View;
|
|||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
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.jobs.MultiDeviceContactUpdateJob;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
|
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.preferences.CorrectedPreferenceFragment;
|
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.preferences.widgets.ContactPreference;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||||
|
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||||
import org.thoughtcrime.securesms.util.Dialogs;
|
import org.thoughtcrime.securesms.util.Dialogs;
|
||||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
@ -378,10 +382,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
|||||||
|
|
||||||
if (recipient.isGroupRecipient()) {
|
if (recipient.isGroupRecipient()) {
|
||||||
if (colorPreference != null) colorPreference.setVisible(false);
|
if (colorPreference != null) colorPreference.setVisible(false);
|
||||||
if (blockPreference != null) blockPreference.setVisible(false);
|
|
||||||
if (identityPreference != null) identityPreference.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 (aboutCategory != null) getPreferenceScreen().removePreference(aboutCategory);
|
||||||
if (aboutDivider != null) getPreferenceScreen().removePreference(aboutDivider);
|
if (aboutDivider != null) getPreferenceScreen().removePreference(aboutDivider);
|
||||||
} else {
|
} else {
|
||||||
@ -659,31 +660,55 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleBlock() {
|
private void handleBlock() {
|
||||||
new AlertDialog.Builder(getActivity())
|
new AsyncTask<Void, Void, Pair<Integer, Integer>>() {
|
||||||
.setTitle(R.string.RecipientPreferenceActivity_block_this_contact_question)
|
|
||||||
.setMessage(R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact)
|
@Override
|
||||||
.setCancelable(true)
|
protected Pair<Integer, Integer> doInBackground(Void... voids) {
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
int titleRes = R.string.RecipientPreferenceActivity_block_this_contact_question;
|
||||||
.setPositiveButton(R.string.RecipientPreferenceActivity_block, new DialogInterface.OnClickListener() {
|
int bodyRes = R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact;
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
if (recipient.isGroupRecipient()) {
|
||||||
setBlocked(recipient, true);
|
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() {
|
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())
|
new AlertDialog.Builder(getActivity())
|
||||||
.setTitle(R.string.RecipientPreferenceActivity_unblock_this_contact_question)
|
.setTitle(titleRes)
|
||||||
.setMessage(R.string.RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
|
.setMessage(bodyRes)
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock, (dialog, which) -> setBlocked(recipient, false)).show();
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
setBlocked(recipient, false);
|
|
||||||
}
|
|
||||||
}).show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBlocked(final Recipient recipient, final boolean blocked) {
|
private void setBlocked(final Recipient recipient, final boolean blocked) {
|
||||||
@ -695,6 +720,23 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
|||||||
DatabaseFactory.getRecipientDatabase(context)
|
DatabaseFactory.getRecipientDatabase(context)
|
||||||
.setBlocked(recipient, blocked);
|
.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)
|
ApplicationContext.getInstance(context)
|
||||||
.getJobManager()
|
.getJobManager()
|
||||||
.add(new MultiDeviceBlockedUpdateJob(context));
|
.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.SignalServiceMessageReceiver;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
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 org.whispersystems.signalservice.api.websocket.ConnectivityListener;
|
||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
@ -124,10 +127,13 @@ public class SignalCommunicationModule {
|
|||||||
@Provides
|
@Provides
|
||||||
synchronized SignalServiceMessageReceiver provideSignalMessageReceiver() {
|
synchronized SignalServiceMessageReceiver provideSignalMessageReceiver() {
|
||||||
if (this.messageReceiver == null) {
|
if (this.messageReceiver == null) {
|
||||||
|
SleepTimer sleepTimer = TextSecurePreferences.isGcmDisabled(context) ? new RealtimeSleepTimer(context) : new UptimeSleepTimer();
|
||||||
|
|
||||||
this.messageReceiver = new SignalServiceMessageReceiver(networkAccess.getConfiguration(context),
|
this.messageReceiver = new SignalServiceMessageReceiver(networkAccess.getConfiguration(context),
|
||||||
new DynamicCredentialsProvider(context),
|
new DynamicCredentialsProvider(context),
|
||||||
BuildConfig.USER_AGENT,
|
BuildConfig.USER_AGENT,
|
||||||
new PipeConnectivityListener());
|
new PipeConnectivityListener(),
|
||||||
|
sleepTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.messageReceiver;
|
return this.messageReceiver;
|
||||||
|
@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
|||||||
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
|
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
|
||||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||||
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage;
|
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage;
|
||||||
@ -47,17 +48,20 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje
|
|||||||
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
|
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
|
||||||
|
|
||||||
try (RecipientReader reader = database.readerForBlocked(database.getBlocked())) {
|
try (RecipientReader reader = database.readerForBlocked(database.getBlocked())) {
|
||||||
List<String> blocked = new LinkedList<>();
|
List<String> blockedIndividuals = new LinkedList<>();
|
||||||
|
List<byte[]> blockedGroups = new LinkedList<>();
|
||||||
|
|
||||||
Recipient recipient;
|
Recipient recipient;
|
||||||
|
|
||||||
while ((recipient = reader.getNext()) != null) {
|
while ((recipient = reader.getNext()) != null) {
|
||||||
if (!recipient.isGroupRecipient()) {
|
if (recipient.isGroupRecipient()) {
|
||||||
blocked.add(recipient.getAddress().serialize());
|
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()),
|
out.write(new DeviceGroup(record.getId(), Optional.fromNullable(record.getTitle()),
|
||||||
members, getAvatar(record.getAvatar()),
|
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);
|
SignalServiceContent content = cipher.decrypt(envelope);
|
||||||
|
|
||||||
|
if (shouldIgnore(envelope, content)) {
|
||||||
|
Log.i(TAG, "Ignoring message.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (content.getDataMessage().isPresent()) {
|
if (content.getDataMessage().isPresent()) {
|
||||||
SignalServiceDataMessage message = content.getDataMessage().get();
|
SignalServiceDataMessage message = content.getDataMessage().get();
|
||||||
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent();
|
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);
|
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()) {
|
if (envelope.isReceipt()) {
|
||||||
handleReceipt(envelope);
|
handleReceipt(envelope);
|
||||||
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage()) {
|
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage()) {
|
||||||
handleMessage(envelope, source);
|
handleMessage(envelope);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
|
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleMessage(SignalServiceEnvelope envelope, Address source) {
|
private void handleMessage(SignalServiceEnvelope envelope) {
|
||||||
Recipient recipients = Recipient.from(context, source, false);
|
long messageId = DatabaseFactory.getPushDatabase(context).insert(envelope);
|
||||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
ApplicationContext.getInstance(context)
|
||||||
|
.getJobManager()
|
||||||
if (!recipients.isBlocked()) {
|
.add(new PushDecryptJob(context, messageId));
|
||||||
long messageId = DatabaseFactory.getPushDatabase(context).insert(envelope);
|
|
||||||
jobManager.add(new PushDecryptJob(context, messageId));
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, "*** Received blocked push message, ignoring...");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleReceipt(SignalServiceEnvelope envelope) {
|
private void handleReceipt(SignalServiceEnvelope envelope) {
|
||||||
|
@ -3,14 +3,23 @@ package org.thoughtcrime.securesms.util;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.annotation.WorkerThread;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
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.logging.Log;
|
||||||
|
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
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.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
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_SIGNAL_GROUP_PREFIX = "__textsecure_group__!";
|
||||||
private static final String ENCODED_MMS_GROUP_PREFIX = "__signal_mms_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) {
|
public static String getEncodedId(byte[] groupId, boolean mms) {
|
||||||
return (mms ? ENCODED_MMS_GROUP_PREFIX : ENCODED_SIGNAL_GROUP_PREFIX) + Hex.toStringCondensed(groupId);
|
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);
|
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) {
|
public static @NonNull GroupDescription getDescription(@NonNull Context context, @Nullable String encodedGroup) {
|
||||||
if (encodedGroup == null) {
|
if (encodedGroup == null) {
|
||||||
return new GroupDescription(context, null);
|
return new GroupDescription(context, null);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user