Skip to content

Commit

Permalink
Implement additional message request improvements.
Browse files Browse the repository at this point in the history
  • Loading branch information
greyson-signal committed Feb 26, 2020
1 parent 81c7887 commit 1faf196
Show file tree
Hide file tree
Showing 43 changed files with 1,514 additions and 352 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,11 @@
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencyProvider;
import org.thoughtcrime.securesms.gcm.FcmJobService;
import org.thoughtcrime.securesms.insights.InsightsOptOut;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob;
import org.thoughtcrime.securesms.jobs.FcmRefreshJob;
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob;
import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob;
import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository;
import org.thoughtcrime.securesms.logging.AndroidLogger;
import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger;
import org.thoughtcrime.securesms.logging.Log;
Expand All @@ -63,6 +58,7 @@
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.ringrtc.RingRtcLogger;
import org.thoughtcrime.securesms.service.DirectoryRefreshListener;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
Expand All @@ -73,10 +69,8 @@
import org.thoughtcrime.securesms.service.RotateSenderCertificateListener;
import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener;
import org.thoughtcrime.securesms.service.UpdateApkRefreshListener;
import org.thoughtcrime.securesms.stickers.BlessedPacks;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
import org.webrtc.voiceengine.WebRtcAudioManager;
Expand Down Expand Up @@ -153,7 +147,7 @@ public void onCreate() {
public void onStart(@NonNull LifecycleOwner owner) {
isAppVisible = true;
Log.i(TAG, "App is now visible.");
FeatureFlags.refresh();
FeatureFlags.refreshIfNecessary();
ApplicationDependencies.getRecipientCache().warmUp();
executePendingContactSync();
KeyCachingService.onAppForegrounded(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;

import java.util.ArrayList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.core.text.HtmlCompat;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.RecyclerView;

Expand Down Expand Up @@ -152,6 +151,7 @@
import org.thoughtcrime.securesms.insights.InsightsLauncher;
import org.thoughtcrime.securesms.invites.InviteReminderModel;
import org.thoughtcrime.securesms.invites.InviteReminderRepository;
import org.thoughtcrime.securesms.jobs.LeaveGroupJob;
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
Expand Down Expand Up @@ -216,7 +216,6 @@
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.HtmlUtil;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.MessageUtil;
Expand Down Expand Up @@ -1120,7 +1119,7 @@ private void handleLeavePushGroup() {
Optional<OutgoingGroupMediaMessage> leaveMessage = GroupUtil.createGroupLeaveMessage(this, groupRecipient);

if (threadId != -1 && leaveMessage.isPresent()) {
MessageSender.send(this, leaveMessage.get(), threadId, false, null);
ApplicationDependencies.getJobManager().add(LeaveGroupJob.create(groupRecipient));

GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(this);
String groupId = groupRecipient.requireGroupId();
Expand Down Expand Up @@ -2043,7 +2042,7 @@ private void setActionBarColor(MaterialColor color) {
}

private void setBlockedUserState(Recipient recipient, boolean isSecureText, boolean isDefaultSms) {
if (recipient.isBlocked()) {
if (recipient.isBlocked() && !FeatureFlags.messageRequests()) {
unblockButton.setVisibility(View.VISIBLE);
composePanel.setVisibility(View.GONE);
makeDefaultSmsButton.setVisibility(View.GONE);
Expand All @@ -2067,7 +2066,11 @@ private void setBlockedUserState(Recipient recipient, boolean isSecureText, bool
}

private void setGroupShareProfileReminder(@NonNull Recipient recipient) {
if (!shouldDisplayMessageRequestUi && recipient.isPushGroup() && !recipient.isProfileSharing()) {
if (FeatureFlags.messageRequests()) {
return;
}

if (recipient.isPushGroup() && !recipient.isProfileSharing()) {
groupShareProfileView.get().setRecipient(recipient);
groupShareProfileView.get().setVisibility(View.VISIBLE);
} else if (groupShareProfileView.resolved()) {
Expand Down Expand Up @@ -2777,14 +2780,14 @@ public void setEnabled(boolean enabled) {

@Override
public void onMessageRequest(@NonNull MessageRequestViewModel viewModel) {

messageRequestBottomView.setAcceptOnClickListener(v -> viewModel.accept());
messageRequestBottomView.setDeleteOnClickListener(v -> viewModel.delete());
messageRequestBottomView.setBlockOnClickListener(v -> viewModel.block());
messageRequestBottomView.setAcceptOnClickListener(v -> viewModel.onAccept());
messageRequestBottomView.setDeleteOnClickListener(v -> onMessageRequestDeleteClicked(viewModel));
messageRequestBottomView.setBlockOnClickListener(v -> onMessageRequestBlockClicked(viewModel));
messageRequestBottomView.setUnblockOnClickListener(v -> onMessageRequestUnblockClicked(viewModel));

viewModel.getRecipient().observe(this, this::presentMessageRequestBottomViewTo);
viewModel.getShouldDisplayMessageRequest().observe(this, this::handleShouldDisplayMessageRequest);
viewModel.getMesasgeRequestStatus().observe(this, status -> {
viewModel.getMessageRequestDisplayState().observe(this, this::presentMessageRequestDisplayState);
viewModel.getMessageRequestStatus().observe(this, status -> {
switch (status) {
case ACCEPTED:
messageRequestBottomView.setVisibility(View.GONE);
Expand Down Expand Up @@ -2909,14 +2912,104 @@ public void onAttachmentChanged() {
updateLinkPreviewState();
}

private void handleShouldDisplayMessageRequest(boolean shouldDisplayMessageRequest) {
shouldDisplayMessageRequestUi = shouldDisplayMessageRequest;
setGroupShareProfileReminder(recipient.get());
private void onMessageRequestDeleteClicked(@NonNull MessageRequestViewModel requestModel) {
Recipient recipient = requestModel.getRecipient().getValue();
if (recipient == null) {
Log.w(TAG, "[onMessageRequestDeleteClicked] No recipient!");
return;
}

AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setNeutralButton(R.string.ConversationActivity_cancel, (d, w) -> d.dismiss());

if (recipient.isGroup() && recipient.isBlocked()) {
builder.setTitle(R.string.ConversationActivity_delete_conversation);
builder.setMessage(R.string.ConversationActivity_this_conversation_will_be_deleted_from_all_of_your_devices);
builder.setPositiveButton(R.string.ConversationActivity_delete, (d, w) -> requestModel.onDelete());
} else if (recipient.isGroup()) {
builder.setTitle(R.string.ConversationActivity_delete_and_leave_group);
builder.setMessage(R.string.ConversationActivity_you_will_leave_this_group_and_it_will_be_deleted_from_all_of_your_devices);
builder.setNegativeButton(R.string.ConversationActivity_delete_and_leave, (d, w) -> requestModel.onDelete());
} else {
builder.setTitle(R.string.ConversationActivity_delete_conversation);
builder.setMessage(R.string.ConversationActivity_this_conversation_will_be_deleted_from_all_of_your_devices);
builder.setNegativeButton(R.string.ConversationActivity_delete, (d, w) -> requestModel.onDelete());
}

builder.show();
}

private void onMessageRequestBlockClicked(@NonNull MessageRequestViewModel requestModel) {
Recipient recipient = requestModel.getRecipient().getValue();
if (recipient == null) {
Log.w(TAG, "[onMessageRequestBlockClicked] No recipient!");
return;
}

AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setNeutralButton(R.string.ConversationActivity_cancel, (d, w) -> d.dismiss())
.setPositiveButton(R.string.ConversationActivity_block_and_delete, (d, w) -> requestModel.onBlockAndDelete())
.setNegativeButton(R.string.ConversationActivity_block, (d, w) -> requestModel.onBlock());

if (recipient.isGroup()) {
builder.setTitle(getString(R.string.ConversationActivity_block_and_leave_s, recipient.getDisplayName(this)));
builder.setMessage(R.string.ConversationActivity_you_will_leave_this_group_and_no_longer_receive_messages_or_updates);
} else {
builder.setTitle(getString(R.string.ConversationActivity_block_s, recipient.getDisplayName(this)));
builder.setMessage(R.string.ConversationActivity_blocked_people_will_not_be_able_to_call_you_or_send_you_messages);
}

builder.show();
}

private void onMessageRequestUnblockClicked(@NonNull MessageRequestViewModel requestModel) {
Recipient recipient = requestModel.getRecipient().getValue();
if (recipient == null) {
Log.w(TAG, "[onMessageRequestUnblockClicked] No recipient!");
return;
}

AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle(getString(R.string.ConversationActivity_unblock_s, recipient.getDisplayName(this)))
.setNeutralButton(R.string.ConversationActivity_cancel, (d, w) -> d.dismiss())
.setNegativeButton(R.string.ConversationActivity_unblock, (d, w) -> requestModel.onUnblock());

if (recipient.isGroup()) {
builder.setMessage(R.string.ConversationActivity_group_members_will_be_able_to_add_you_to_this_group_again);
} else {
builder.setMessage(R.string.ConversationActivity_you_will_be_able_to_message_and_call_each_other);
}

builder.show();
}

private void presentMessageRequestDisplayState(@NonNull MessageRequestViewModel.DisplayState displayState) {
if (getIntent().hasExtra(TEXT_EXTRA) || getIntent().hasExtra(MEDIA_EXTRA) || getIntent().hasExtra(STICKER_EXTRA) || (isPushGroupConversation() && !isActiveGroup())) {
Log.d(TAG, "[presentMessageRequestDisplayState] Have extra, so ignoring provided state.");
messageRequestBottomView.setVisibility(View.GONE);
} else {
messageRequestBottomView.setVisibility(shouldDisplayMessageRequest ? View.VISIBLE : View.GONE);
Log.d(TAG, "[presentMessageRequestDisplayState] " + displayState);
switch (displayState) {
case DISPLAY_MESSAGE_REQUEST:
messageRequestBottomView.setVisibility(View.VISIBLE);
if (groupShareProfileView.resolved()) {
groupShareProfileView.get().setVisibility(View.GONE);
}
break;
case DISPLAY_LEGACY:
if (recipient.get().isGroup()) {
groupShareProfileView.get().setRecipient(recipient.get());
groupShareProfileView.get().setVisibility(View.VISIBLE);
}
messageRequestBottomView.setVisibility(View.GONE);
break;
case DISPLAY_NONE:
messageRequestBottomView.setVisibility(View.GONE);
if (groupShareProfileView.resolved()) {
groupShareProfileView.get().setVisibility(View.GONE);
}
break;
}
}

invalidateOptionsMenu();
Expand Down Expand Up @@ -3019,6 +3112,6 @@ protected void onPostExecute(MessageRecord messageRecord) {
private void presentMessageRequestBottomViewTo(@Nullable Recipient recipient) {
if (recipient == null) return;

messageRequestBottomView.setQuestionText(HtmlCompat.fromHtml(getString(R.string.MessageRequestBottomView_do_you_want_to_let, HtmlUtil.bold(recipient.getDisplayName(this))), 0));
messageRequestBottomView.setRecipient(recipient);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import org.thoughtcrime.securesms.MessageDetailsActivity;
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.sharing.ShareActivity;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.components.ConversationTypingView;
import org.thoughtcrime.securesms.components.TooltipPopup;
Expand Down Expand Up @@ -155,7 +156,6 @@ public class ConversationFragment extends Fragment
private int activeOffset;
private boolean firstLoad;
private boolean isReacting;
private boolean shouldDisplayMessageRequest;
private ActionMode actionMode;
private Locale locale;
private RecyclerView list;
Expand Down Expand Up @@ -206,7 +206,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,

new ConversationItemSwipeCallback(
messageRecord -> actionMode == null &&
canReplyToMessage(isActionMessage(messageRecord), messageRecord, shouldDisplayMessageRequest),
canReplyToMessage(isActionMessage(messageRecord), messageRecord, messageRequestViewModel.shouldShowMessageRequest()),
this::handleReplyMessage
).attachToRecyclerView(list);

Expand Down Expand Up @@ -334,12 +334,6 @@ private void initializeMessageRequestViewModel() {
presentMessageRequestProfileView(requireContext(), recipientInfo, conversationBanner);
presentMessageRequestProfileView(requireContext(), recipientInfo, emptyConversationBanner);
});

messageRequestViewModel.getShouldDisplayMessageRequest().observe(getViewLifecycleOwner(), this::handleShouldDisplayMessageRequest);
}

private void handleShouldDisplayMessageRequest(boolean shouldDisplayMessageRequest) {
this.shouldDisplayMessageRequest = shouldDisplayMessageRequest;
}

private static void presentMessageRequestProfileView(@NonNull Context context, @NonNull MessageRequestViewModel.RecipientInfo recipientInfo, @Nullable ConversationBannerView conversationBanner) {
Expand Down Expand Up @@ -558,7 +552,7 @@ private void setCorrectMenuVisibility(Menu menu) {

menu.findItem(R.id.menu_context_forward).setVisible(!actionMessage && !sharedContact && !viewOnce);
menu.findItem(R.id.menu_context_details).setVisible(!actionMessage);
menu.findItem(R.id.menu_context_reply).setVisible(canReplyToMessage(actionMessage, messageRecord, shouldDisplayMessageRequest));
menu.findItem(R.id.menu_context_reply).setVisible(canReplyToMessage(actionMessage, messageRecord, messageRequestViewModel.shouldShowMessageRequest()));
}
menu.findItem(R.id.menu_context_copy).setVisible(!actionMessage && hasText);
}
Expand Down Expand Up @@ -839,8 +833,8 @@ public void onClick(DialogInterface dialog, int which) {

@Override
public void onLoadFinished(@NonNull Loader<Cursor> cursorLoader, Cursor cursor) {
int count = cursor.getCount();
ConversationLoader loader = (ConversationLoader)cursorLoader;
int count = cursor.getCount();
ConversationLoader loader = (ConversationLoader) cursorLoader;

ConversationAdapter adapter = getListAdapter();
if (adapter == null) {
Expand All @@ -859,7 +853,7 @@ public void onLoadFinished(@NonNull Loader<Cursor> cursorLoader, Cursor cursor)
setLastSeen(loader.getLastSeen());
}

if (FeatureFlags.messageRequests()) {
if (FeatureFlags.messageRequests() && !loader.hasPreMessageRequestMessages()) {
clearHeaderIfNotTyping(adapter);
} else {
if (!loader.hasSent() && !recipient.get().isSystemContact() && !recipient.get().isGroup() && recipient.get().getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) {
Expand Down Expand Up @@ -1139,10 +1133,10 @@ public void onItemLongClick(View maskTarget, MessageRecord messageRecord) {

if (actionMode != null) return;

if (messageRecord.isSecure() &&
!messageRecord.isUpdate() &&
!recipient.get().isBlocked() &&
!shouldDisplayMessageRequest &&
if (messageRecord.isSecure() &&
!messageRecord.isUpdate() &&
!recipient.get().isBlocked() &&
!messageRequestViewModel.shouldShowMessageRequest() &&
((ConversationAdapter) list.getAdapter()).getSelectedItems().isEmpty())
{
isReacting = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import org.thoughtcrime.securesms.conversationlist.model.MessageResult;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.SearchUtil;
import org.thoughtcrime.securesms.util.SpanUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.ViewUtil;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import net.sqlcipher.database.SQLiteDatabase;

import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.BitmapUtil;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,16 +282,31 @@ public long getLatestGroupQuitTimestamp(long threadId, long quitTimeBarrier) {

public int getMessageCountForThread(long threadId) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
Cursor cursor = null;

try {
cursor = db.query(TABLE_NAME, new String[] {"COUNT(*)"}, THREAD_ID + " = ?", new String[] {threadId+""}, null, null, null);
String[] cols = new String[] {"COUNT(*)"};
String query = THREAD_ID + " = ?";
String[] args = new String[]{String.valueOf(threadId)};

if (cursor != null && cursor.moveToFirst())
try (Cursor cursor = db.query(TABLE_NAME, cols, query, args, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getInt(0);
} finally {
if (cursor != null)
cursor.close();
}
}

return 0;
}

public int getMessageCountForThread(long threadId, long beforeTime) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();

String[] cols = new String[] {"COUNT(*)"};
String query = THREAD_ID + " = ? AND " + DATE_RECEIVED + " < ?";
String[] args = new String[]{String.valueOf(threadId), String.valueOf(beforeTime)};

try (Cursor cursor = db.query(TABLE_NAME, cols, query, args, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getInt(0);
}
}

return 0;
Expand Down

0 comments on commit 1faf196

Please sign in to comment.