diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 365a4b29c..67218f62d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -243,12 +243,6 @@
android:theme="@style/TextSecure.LightTheme.Popup"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
-
-
.
- */
-package org.thoughtcrime.securesms;
-
-import android.annotation.SuppressLint;
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.database.Cursor;
-import android.graphics.drawable.ColorDrawable;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.loader.app.LoaderManager.LoaderCallbacks;
-import androidx.loader.content.Loader;
-
-import org.thoughtcrime.securesms.conversation.ConversationItem;
-import org.thoughtcrime.securesms.database.GroupDatabase;
-import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
-import org.thoughtcrime.securesms.logging.Log;
-
-import android.os.Parcelable;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import org.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
-import org.thoughtcrime.securesms.color.MaterialColor;
-import org.thoughtcrime.securesms.database.DatabaseFactory;
-import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
-import org.thoughtcrime.securesms.database.GroupReceiptDatabase.GroupReceiptInfo;
-import org.thoughtcrime.securesms.database.MmsDatabase;
-import org.thoughtcrime.securesms.database.MmsSmsDatabase;
-import org.thoughtcrime.securesms.database.SmsDatabase;
-import org.thoughtcrime.securesms.database.loaders.MessageDetailsLoader;
-import org.thoughtcrime.securesms.database.model.MessageRecord;
-import org.thoughtcrime.securesms.mms.GlideApp;
-import org.thoughtcrime.securesms.mms.GlideRequests;
-import org.thoughtcrime.securesms.recipients.LiveRecipient;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.sms.MessageSender;
-import org.thoughtcrime.securesms.util.DateUtils;
-import org.thoughtcrime.securesms.util.DynamicDarkActionBarTheme;
-import org.thoughtcrime.securesms.util.DynamicLanguage;
-import org.thoughtcrime.securesms.util.DynamicTheme;
-import org.thoughtcrime.securesms.util.ExpirationUtil;
-import org.thoughtcrime.securesms.util.Util;
-import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
-import org.whispersystems.libsignal.util.guava.Optional;
-
-import java.lang.ref.WeakReference;
-import java.sql.Date;
-import java.text.SimpleDateFormat;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * @author Jake McGinty
- */
-public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity implements LoaderCallbacks {
- private final static String TAG = MessageDetailsActivity.class.getSimpleName();
-
- public static final String MESSAGE_ID_EXTRA = "message_id";
- public static final String THREAD_ID_EXTRA = "thread_id";
- public static final String IS_PUSH_GROUP_EXTRA = "is_push_group";
- public static final String TYPE_EXTRA = "type";
- public static final String RECIPIENT_EXTRA = "recipient_id";
-
- private GlideRequests glideRequests;
- private long threadId;
- private boolean isPushGroup;
- private ConversationItem conversationItem;
- private ViewGroup itemParent;
- private View metadataContainer;
- private View expiresContainer;
- private TextView errorText;
- private View resendButton;
- private TextView sentDate;
- private TextView receivedDate;
- private TextView expiresInText;
- private View receivedContainer;
- private TextView transport;
- private TextView toFrom;
- private ListView recipientsList;
- private LayoutInflater inflater;
-
- private DynamicTheme dynamicTheme = new DynamicDarkActionBarTheme();
- private DynamicLanguage dynamicLanguage = new DynamicLanguage();
-
- private boolean running;
-
- @Override
- protected void onPreCreate() {
- dynamicTheme.onCreate(this);
- dynamicLanguage.onCreate(this);
- }
-
- @Override
- public void onCreate(Bundle bundle, boolean ready) {
- setContentView(R.layout.message_details_activity);
- running = true;
-
- initializeResources();
- initializeActionBar();
- getSupportLoaderManager().initLoader(0, null, this);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- dynamicTheme.onResume(this);
- dynamicLanguage.onResume(this);
-
- assert getSupportActionBar() != null;
- getSupportActionBar().setTitle(R.string.AndroidManifest__message_details);
-
- ApplicationDependencies.getMessageNotifier().setVisibleThread(threadId);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- ApplicationDependencies.getMessageNotifier().clearVisibleThread();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- running = false;
- }
-
- private void initializeActionBar() {
- assert getSupportActionBar() != null;
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- LiveRecipient recipient = Recipient.live(getIntent().getParcelableExtra(RECIPIENT_EXTRA));
- recipient.observe(this, r -> setActionBarColor(r.getColor()));
-
- setActionBarColor(recipient.get().getColor());
- }
-
- private void setActionBarColor(MaterialColor color) {
- assert getSupportActionBar() != null;
- getSupportActionBar().setBackgroundDrawable(new ColorDrawable(color.toActionBarColor(this)));
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- getWindow().setStatusBarColor(color.toStatusBarColor(this));
- }
- }
-
- private void initializeResources() {
- inflater = LayoutInflater.from(this);
- View header = inflater.inflate(R.layout.message_details_header, recipientsList, false);
-
- threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
- isPushGroup = getIntent().getBooleanExtra(IS_PUSH_GROUP_EXTRA, false);
- glideRequests = GlideApp.with(this);
- itemParent = header.findViewById(R.id.item_container);
- recipientsList = findViewById(R.id.recipients_list);
- metadataContainer = header.findViewById(R.id.metadata_container);
- errorText = header.findViewById(R.id.error_text);
- resendButton = header.findViewById(R.id.resend_button);
- sentDate = header.findViewById(R.id.sent_time);
- receivedContainer = header.findViewById(R.id.received_container);
- receivedDate = header.findViewById(R.id.received_time);
- transport = header.findViewById(R.id.transport);
- toFrom = header.findViewById(R.id.tofrom);
- expiresContainer = header.findViewById(R.id.expires_container);
- expiresInText = header.findViewById(R.id.expires_in);
- recipientsList.setHeaderDividersEnabled(false);
- recipientsList.addHeaderView(header, null, false);
- }
-
- private void updateTransport(MessageRecord messageRecord) {
- final String transportText;
- if (messageRecord.isOutgoing() && messageRecord.isFailed()) {
- transportText = "-";
- } else if (messageRecord.isPending()) {
- transportText = getString(R.string.ConversationFragment_pending);
- } else if (messageRecord.isPush()) {
- transportText = getString(R.string.ConversationFragment_push);
- } else if (messageRecord.isMms()) {
- transportText = getString(R.string.ConversationFragment_mms);
- } else {
- transportText = getString(R.string.ConversationFragment_sms);
- }
-
- transport.setText(transportText);
- }
-
- private void updateTime(MessageRecord messageRecord) {
- sentDate.setOnLongClickListener(null);
- receivedDate.setOnLongClickListener(null);
-
- if (messageRecord.isPending() || messageRecord.isFailed()) {
- sentDate.setText("-");
- receivedContainer.setVisibility(View.GONE);
- } else {
- Locale dateLocale = dynamicLanguage.getCurrentLocale();
- SimpleDateFormat dateFormatter = DateUtils.getDetailedDateFormatter(this, dateLocale);
- sentDate.setText(dateFormatter.format(new Date(messageRecord.getDateSent())));
- sentDate.setOnLongClickListener(v -> {
- copyToClipboard(String.valueOf(messageRecord.getDateSent()));
- return true;
- });
-
- if (messageRecord.getDateReceived() != messageRecord.getDateSent() && !messageRecord.isOutgoing()) {
- receivedDate.setText(dateFormatter.format(new Date(messageRecord.getDateReceived())));
- receivedDate.setOnLongClickListener(v -> {
- copyToClipboard(String.valueOf(messageRecord.getDateReceived()));
- return true;
- });
- receivedContainer.setVisibility(View.VISIBLE);
- } else {
- receivedContainer.setVisibility(View.GONE);
- }
- }
- }
-
- private void updateExpirationTime(final MessageRecord messageRecord) {
- if (messageRecord.getExpiresIn() <= 0 || messageRecord.getExpireStarted() <= 0) {
- expiresContainer.setVisibility(View.GONE);
- return;
- }
-
- expiresContainer.setVisibility(View.VISIBLE);
- Util.runOnMain(new Runnable() {
- @Override
- public void run() {
- long elapsed = System.currentTimeMillis() - messageRecord.getExpireStarted();
- long remaining = messageRecord.getExpiresIn() - elapsed;
-
- String duration = ExpirationUtil.getExpirationDisplayValue(MessageDetailsActivity.this, Math.max((int)(remaining / 1000), 1));
- expiresInText.setText(duration);
-
- if (running) {
- Util.runOnMainDelayed(this, 500);
- }
- }
- });
- }
-
- private void updateRecipients(MessageRecord messageRecord, Recipient recipient, List recipients) {
- final int toFromRes;
- if (messageRecord.isMms() && !messageRecord.isPush() && !messageRecord.isOutgoing()) {
- toFromRes = R.string.message_details_header__with;
- } else if (messageRecord.isOutgoing()) {
- toFromRes = R.string.message_details_header__to;
- } else {
- toFromRes = R.string.message_details_header__from;
- }
- toFrom.setText(toFromRes);
- conversationItem.bind(messageRecord, Optional.absent(), Optional.absent(), glideRequests, dynamicLanguage.getCurrentLocale(), new HashSet<>(), recipient, null, false);
- Parcelable state = recipientsList.onSaveInstanceState();
- recipientsList.setAdapter(new MessageDetailsRecipientAdapter(this, glideRequests, messageRecord, recipients, isPushGroup));
- recipientsList.onRestoreInstanceState(state);
- }
-
- private void inflateMessageViewIfAbsent(MessageRecord messageRecord) {
- if (conversationItem == null) {
- if (messageRecord.isGroupAction()) {
- conversationItem = (ConversationItem) inflater.inflate(R.layout.conversation_item_update, itemParent, false);
- } else if (messageRecord.isOutgoing()) {
- conversationItem = (ConversationItem) inflater.inflate(R.layout.conversation_item_sent_multimedia, itemParent, false);
- } else {
- conversationItem = (ConversationItem) inflater.inflate(R.layout.conversation_item_received_multimedia, itemParent, false);
- }
- itemParent.addView(conversationItem);
- }
- }
-
- private @Nullable MessageRecord getMessageRecord(Context context, Cursor cursor, String type) {
- switch (type) {
- case MmsSmsDatabase.SMS_TRANSPORT:
- SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
- SmsDatabase.Reader reader = smsDatabase.readerFor(cursor);
- return reader.getNext();
- case MmsSmsDatabase.MMS_TRANSPORT:
- MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
- MmsDatabase.Reader mmsReader = mmsDatabase.readerFor(cursor);
- return mmsReader.getNext();
- default:
- throw new AssertionError("no valid message type specified");
- }
- }
-
- private void copyToClipboard(@NonNull String text) {
- ((ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("text", text));
- }
-
- @Override
- public @NonNull Loader onCreateLoader(int id, Bundle args) {
- return new MessageDetailsLoader(this, getIntent().getStringExtra(TYPE_EXTRA),
- getIntent().getLongExtra(MESSAGE_ID_EXTRA, -1));
- }
-
- @Override
- public void onLoadFinished(@NonNull Loader loader, Cursor cursor) {
- MessageRecord messageRecord = getMessageRecord(this, cursor, getIntent().getStringExtra(TYPE_EXTRA));
-
- if (messageRecord == null) {
- finish();
- } else {
- new MessageRecipientAsyncTask(this, messageRecord).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
- }
-
- @Override
- public void onLoaderReset(@NonNull Loader loader) {
- recipientsList.setAdapter(null);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- super.onOptionsItemSelected(item);
-
- switch (item.getItemId()) {
- case android.R.id.home: finish(); return true;
- }
-
- return false;
- }
-
- @SuppressLint("StaticFieldLeak")
- private class MessageRecipientAsyncTask extends AsyncTask> {
-
- private final WeakReference weakContext;
- private final MessageRecord messageRecord;
-
- MessageRecipientAsyncTask(@NonNull Context context, @NonNull MessageRecord messageRecord) {
- this.weakContext = new WeakReference<>(context);
- this.messageRecord = messageRecord;
- }
-
- protected Context getContext() {
- return weakContext.get();
- }
-
- @Override
- public List doInBackground(Void... voids) {
- Context context = getContext();
-
- if (context == null) {
- Log.w(TAG, "associated context is destroyed, finishing early");
- return null;
- }
-
- List recipients = new LinkedList<>();
-
- if (!messageRecord.getRecipient().isGroup()) {
- recipients.add(new RecipientDeliveryStatus(messageRecord.getRecipient(), getStatusFor(messageRecord.getDeliveryReceiptCount(), messageRecord.getReadReceiptCount(), messageRecord.isPending()), messageRecord.isUnidentified(), -1));
- } else {
- List receiptInfoList = DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageRecord.getId());
-
- if (receiptInfoList.isEmpty()) {
- List group = DatabaseFactory.getGroupDatabase(context).getGroupMembers(messageRecord.getRecipient().requireGroupId(), GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
-
- for (Recipient recipient : group) {
- recipients.add(new RecipientDeliveryStatus(recipient, RecipientDeliveryStatus.Status.UNKNOWN, false, -1));
- }
- } else {
- for (GroupReceiptInfo info : receiptInfoList) {
- recipients.add(new RecipientDeliveryStatus(Recipient.resolved(info.getRecipientId()),
- getStatusFor(info.getStatus(), messageRecord.isPending(), messageRecord.isFailed()),
- info.isUnidentified(),
- info.getTimestamp()));
- }
- }
- }
-
- return recipients;
- }
-
- @Override
- public void onPostExecute(List recipients) {
- if (getContext() == null) {
- Log.w(TAG, "AsyncTask finished with a destroyed context, leaving early.");
- return;
- }
-
- inflateMessageViewIfAbsent(messageRecord);
- updateRecipients(messageRecord, messageRecord.getRecipient(), recipients);
-
- boolean isGroupNetworkFailure = messageRecord.isFailed() && !messageRecord.getNetworkFailures().isEmpty();
- boolean isIndividualNetworkFailure = messageRecord.isFailed() && !isPushGroup && messageRecord.getIdentityKeyMismatches().isEmpty();
-
- if (isGroupNetworkFailure || isIndividualNetworkFailure) {
- errorText.setVisibility(View.VISIBLE);
- resendButton.setVisibility(View.VISIBLE);
- resendButton.setOnClickListener(this::onResendClicked);
- metadataContainer.setVisibility(View.GONE);
- } else if (messageRecord.isFailed()) {
- errorText.setVisibility(View.VISIBLE);
- resendButton.setVisibility(View.GONE);
- resendButton.setOnClickListener(null);
- metadataContainer.setVisibility(View.GONE);
- } else {
- updateTransport(messageRecord);
- updateTime(messageRecord);
- updateExpirationTime(messageRecord);
- errorText.setVisibility(View.GONE);
- resendButton.setVisibility(View.GONE);
- resendButton.setOnClickListener(null);
- metadataContainer.setVisibility(View.VISIBLE);
- }
- }
-
- private RecipientDeliveryStatus.Status getStatusFor(int deliveryReceiptCount, int readReceiptCount, boolean pending) {
- if (readReceiptCount > 0) return RecipientDeliveryStatus.Status.READ;
- else if (deliveryReceiptCount > 0) return RecipientDeliveryStatus.Status.DELIVERED;
- else if (!pending) return RecipientDeliveryStatus.Status.SENT;
- else return RecipientDeliveryStatus.Status.PENDING;
- }
-
- private RecipientDeliveryStatus.Status getStatusFor(int groupStatus, boolean pending, boolean failed) {
- if (groupStatus == GroupReceiptDatabase.STATUS_READ) return RecipientDeliveryStatus.Status.READ;
- else if (groupStatus == GroupReceiptDatabase.STATUS_DELIVERED) return RecipientDeliveryStatus.Status.DELIVERED;
- else if (groupStatus == GroupReceiptDatabase.STATUS_UNDELIVERED && failed) return RecipientDeliveryStatus.Status.UNKNOWN;
- else if (groupStatus == GroupReceiptDatabase.STATUS_UNDELIVERED && !pending) return RecipientDeliveryStatus.Status.SENT;
- else if (groupStatus == GroupReceiptDatabase.STATUS_UNDELIVERED) return RecipientDeliveryStatus.Status.PENDING;
- else if (groupStatus == GroupReceiptDatabase.STATUS_UNKNOWN) return RecipientDeliveryStatus.Status.UNKNOWN;
- throw new AssertionError();
- }
-
- private void onResendClicked(View v) {
- resendButton.setVisibility(View.GONE);
- SignalExecutors.BOUNDED.execute(() -> MessageSender.resend(MessageDetailsActivity.this, messageRecord));
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/MessageDetailsRecipientAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/MessageDetailsRecipientAdapter.java
deleted file mode 100644
index 12a290cc8..000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/MessageDetailsRecipientAdapter.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.thoughtcrime.securesms;
-
-import android.content.Context;
-import androidx.annotation.NonNull;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.BaseAdapter;
-
-import org.thoughtcrime.securesms.database.model.MessageRecord;
-import org.thoughtcrime.securesms.mms.GlideRequests;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.recipients.RecipientId;
-import org.thoughtcrime.securesms.util.Conversions;
-import org.thoughtcrime.securesms.util.adapter.StableIdGenerator;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.List;
-
-class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsListView.RecyclerListener {
-
- private final Context context;
- private final GlideRequests glideRequests;
- private final MessageRecord record;
- private final List members;
- private final boolean isPushGroup;
- private final StableIdGenerator idGenerator;
-
- MessageDetailsRecipientAdapter(@NonNull Context context, @NonNull GlideRequests glideRequests,
- @NonNull MessageRecord record, @NonNull List members,
- boolean isPushGroup)
- {
- this.context = context;
- this.glideRequests = glideRequests;
- this.record = record;
- this.isPushGroup = isPushGroup;
- this.members = members;
- this.idGenerator = new StableIdGenerator<>();
- }
-
- @Override
- public int getCount() {
- return members.size();
- }
-
- @Override
- public Object getItem(int position) {
- return members.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return idGenerator.getId(members.get(position).recipient.getId());
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = LayoutInflater.from(context).inflate(R.layout.message_recipient_list_item, parent, false);
- }
-
- RecipientDeliveryStatus member = members.get(position);
-
- ((MessageRecipientListItem)convertView).set(glideRequests, record, member, isPushGroup);
- return convertView;
- }
-
- @Override
- public void onMovedToScrapHeap(View view) {
- ((MessageRecipientListItem)view).unbind();
- }
-
-
- static class RecipientDeliveryStatus {
-
- enum Status {
- UNKNOWN, PENDING, SENT, DELIVERED, READ
- }
-
- private final Recipient recipient;
- private final Status deliveryStatus;
- private final boolean isUnidentified;
- private final long timestamp;
-
- RecipientDeliveryStatus(Recipient recipient, Status deliveryStatus, boolean isUnidentified, long timestamp) {
- this.recipient = recipient;
- this.deliveryStatus = deliveryStatus;
- this.isUnidentified = isUnidentified;
- this.timestamp = timestamp;
- }
-
- Status getDeliveryStatus() {
- return deliveryStatus;
- }
-
- boolean isUnidentified() {
- return isUnidentified;
- }
-
- public long getTimestamp() {
- return timestamp;
- }
-
- public Recipient getRecipient() {
- return recipient;
- }
-
- }
-
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/MessageRecipientListItem.java b/app/src/main/java/org/thoughtcrime/securesms/MessageRecipientListItem.java
deleted file mode 100644
index 3ff3016c9..000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/MessageRecipientListItem.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2014 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-
-import org.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
-import org.thoughtcrime.securesms.components.AvatarImageView;
-import org.thoughtcrime.securesms.components.DeliveryStatusView;
-import org.thoughtcrime.securesms.components.FromTextView;
-import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
-import org.thoughtcrime.securesms.database.documents.NetworkFailure;
-import org.thoughtcrime.securesms.database.model.MessageRecord;
-import org.thoughtcrime.securesms.logging.Log;
-import org.thoughtcrime.securesms.mms.GlideRequests;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-
-/**
- * A simple view to show the recipients of a message
- *
- * @author Jake McGinty
- */
-public class MessageRecipientListItem extends RelativeLayout
- implements RecipientForeverObserver
-{
- @SuppressWarnings("unused")
- private final static String TAG = MessageRecipientListItem.class.getSimpleName();
-
- private RecipientDeliveryStatus member;
- private GlideRequests glideRequests;
- private FromTextView fromView;
- private TextView errorDescription;
- private TextView actionDescription;
- private Button conflictButton;
- private AvatarImageView contactPhotoImage;
- private ImageView unidentifiedDeliveryIcon;
- private DeliveryStatusView deliveryStatusView;
-
- public MessageRecipientListItem(Context context) {
- super(context);
- }
-
- public MessageRecipientListItem(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- this.fromView = findViewById(R.id.from);
- this.errorDescription = findViewById(R.id.error_description);
- this.actionDescription = findViewById(R.id.action_description);
- this.contactPhotoImage = findViewById(R.id.contact_photo_image);
- this.conflictButton = findViewById(R.id.conflict_button);
- this.unidentifiedDeliveryIcon = findViewById(R.id.ud_indicator);
- this.deliveryStatusView = findViewById(R.id.delivery_status);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- observeMember();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- unsubscribeFromMember();
- super.onDetachedFromWindow();
- }
-
- public void set(final GlideRequests glideRequests,
- final MessageRecord record,
- final RecipientDeliveryStatus member,
- final boolean isPushGroup)
- {
- unsubscribeFromMember();
-
- this.glideRequests = glideRequests;
- this.member = member;
- observeMember();
-
- fromView.setText(member.getRecipient());
- contactPhotoImage.setAvatar(glideRequests, member.getRecipient(), false);
- setIssueIndicators(record, isPushGroup);
- unidentifiedDeliveryIcon.setVisibility(TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(getContext()) && member.isUnidentified() ? VISIBLE : GONE);
- }
-
- private void observeMember() {
- if (isAttachedToWindow() && member != null && member.getRecipient() != null) {
- member.getRecipient().live().observeForever(this);
- }
- }
-
- private void unsubscribeFromMember() {
- if (member != null && member.getRecipient() != null) member.getRecipient().live().removeForeverObserver(this);
- }
-
- private void setIssueIndicators(final MessageRecord record,
- final boolean isPushGroup)
- {
- final NetworkFailure networkFailure = getNetworkFailure(record);
- final IdentityKeyMismatch keyMismatch = networkFailure == null ? getKeyMismatch(record) : null;
-
- String errorText = "";
-
- if (keyMismatch != null) {
- conflictButton.setVisibility(View.VISIBLE);
-
- errorText = getContext().getString(R.string.MessageDetailsRecipient_new_safety_number);
- conflictButton.setOnClickListener(v -> new ConfirmIdentityDialog(getContext(), record, keyMismatch).show());
- } else if ((networkFailure != null && !record.isPending()) || (!isPushGroup && record.isFailed())) {
- conflictButton.setVisibility(View.GONE);
- errorText = getContext().getString(R.string.MessageDetailsRecipient_failed_to_send);
- } else {
- if (record.isOutgoing()) {
- if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.PENDING || member.getDeliveryStatus() == RecipientDeliveryStatus.Status.UNKNOWN) {
- deliveryStatusView.setVisibility(View.GONE);
- } else if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.READ) {
- deliveryStatusView.setRead();
- deliveryStatusView.setVisibility(View.VISIBLE);
- } else if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.DELIVERED) {
- deliveryStatusView.setDelivered();
- deliveryStatusView.setVisibility(View.VISIBLE);
- } else if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.SENT) {
- deliveryStatusView.setSent();
- deliveryStatusView.setVisibility(View.VISIBLE);
- }
- } else {
- deliveryStatusView.setVisibility(View.GONE);
- }
-
- conflictButton.setVisibility(View.GONE);
- }
-
- errorDescription.setText(errorText);
- errorDescription.setVisibility(TextUtils.isEmpty(errorText) ? View.GONE : View.VISIBLE);
- }
-
- private NetworkFailure getNetworkFailure(final MessageRecord record) {
- if (record.hasNetworkFailures()) {
- for (final NetworkFailure failure : record.getNetworkFailures()) {
- if (failure.getRecipientId(getContext()).equals(member.getRecipient().getId())) {
- return failure;
- }
- }
- }
- return null;
- }
-
- private IdentityKeyMismatch getKeyMismatch(final MessageRecord record) {
- if (record.isIdentityMismatchFailure()) {
- for (final IdentityKeyMismatch mismatch : record.getIdentityKeyMismatches()) {
- if (mismatch.getRecipientId(getContext()).equals(member.getRecipient().getId())) {
- return mismatch;
- }
- }
- }
- return null;
- }
-
- public void unbind() {
- unsubscribeFromMember();
- }
-
- @Override
- public void onRecipientChanged(@NonNull Recipient recipient) {
- if (this.member != null && this.member.getRecipient().equals(recipient)) {
- Log.d(TAG, "onRecipientChanged -- valid");
- fromView.setText(recipient);
- contactPhotoImage.setAvatar(glideRequests, recipient, false);
- } else {
- Log.d(TAG, "onRecipientChanged -- invalid");
- }
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java
index 3539433ec..11060918f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java
@@ -60,7 +60,6 @@ import com.annimon.stream.Stream;
import com.google.android.collect.Sets;
import org.thoughtcrime.securesms.ApplicationContext;
-import org.thoughtcrime.securesms.MessageDetailsActivity;
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.Attachment;
@@ -74,7 +73,6 @@ import org.thoughtcrime.securesms.conversation.ConversationAdapter.ItemClickList
import org.thoughtcrime.securesms.conversation.ConversationAdapter.StickyHeaderViewHolder;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase;
-import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
@@ -87,6 +85,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.longmessage.LongMessageActivity;
import org.thoughtcrime.securesms.mediasend.Media;
+import org.thoughtcrime.securesms.messagedetails.MessageDetailsActivity;
import org.thoughtcrime.securesms.messagerequests.MessageRequestViewModel;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@@ -690,13 +689,7 @@ public class ConversationFragment extends Fragment {
private void handleDisplayDetails(MessageRecord message) {
- Intent intent = new Intent(getActivity(), org.thoughtcrime.securesms.messagedetails.MessageDetailsActivity.class);
- intent.putExtra(MessageDetailsActivity.MESSAGE_ID_EXTRA, message.getId());
- intent.putExtra(MessageDetailsActivity.THREAD_ID_EXTRA, threadId);
- intent.putExtra(MessageDetailsActivity.TYPE_EXTRA, message.isMms() ? MmsSmsDatabase.MMS_TRANSPORT : MmsSmsDatabase.SMS_TRANSPORT);
- intent.putExtra(MessageDetailsActivity.RECIPIENT_EXTRA, recipient.getId());
- intent.putExtra(MessageDetailsActivity.IS_PUSH_GROUP_EXTRA, recipient.get().isGroup() && message.isPush());
- startActivity(intent);
+ startActivity(MessageDetailsActivity.getIntentForMessageDetails(requireContext(), message, recipient.getId(), threadId));
}
private void handleForwardMessage(MessageRecord message) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java
index 2742a5439..9a9be3bd1 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java
@@ -58,7 +58,6 @@ import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.BindableConversationItem;
import org.thoughtcrime.securesms.ConfirmIdentityDialog;
import org.thoughtcrime.securesms.MediaPreviewActivity;
-import org.thoughtcrime.securesms.MessageDetailsActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.components.AlertView;
@@ -77,7 +76,6 @@ import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
-import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
@@ -92,6 +90,7 @@ import org.thoughtcrime.securesms.jobs.SmsSendJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.thoughtcrime.securesms.logging.Log;
+import org.thoughtcrime.securesms.messagedetails.MessageDetailsActivity;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.ImageSlide;
import org.thoughtcrime.securesms.mms.PartAuthority;
@@ -109,7 +108,6 @@ import org.thoughtcrime.securesms.revealable.ViewOnceUtil;
import org.thoughtcrime.securesms.stickers.StickerUrl;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.DynamicTheme;
-import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.LongClickCopySpan;
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
import org.thoughtcrime.securesms.util.SearchUtil;
@@ -1377,13 +1375,7 @@ public class ConversationItem extends LinearLayout implements BindableConversati
if (!shouldInterceptClicks(messageRecord) && parent != null) {
parent.onClick(v);
} else if (messageRecord.isFailed()) {
- Intent intent = new Intent(context, org.thoughtcrime.securesms.messagedetails.MessageDetailsActivity.class);
- intent.putExtra(MessageDetailsActivity.MESSAGE_ID_EXTRA, messageRecord.getId());
- intent.putExtra(MessageDetailsActivity.THREAD_ID_EXTRA, messageRecord.getThreadId());
- intent.putExtra(MessageDetailsActivity.TYPE_EXTRA, messageRecord.isMms() ? MmsSmsDatabase.MMS_TRANSPORT : MmsSmsDatabase.SMS_TRANSPORT);
- intent.putExtra(MessageDetailsActivity.IS_PUSH_GROUP_EXTRA, groupThread && messageRecord.isPush());
- intent.putExtra(MessageDetailsActivity.RECIPIENT_EXTRA, conversationRecipient.getId());
- context.startActivity(intent);
+ context.startActivity(MessageDetailsActivity.getIntentForMessageDetails(context, messageRecord, conversationRecipient.getId(), messageRecord.getThreadId()));
} else if (!messageRecord.isOutgoing() && messageRecord.isIdentityMismatchFailure()) {
handleApproveIdentity();
} else if (messageRecord.isPendingInsecureSmsFallback()) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsActivity.java b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsActivity.java
index 2b8711f3e..4253afde9 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsActivity.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsActivity.java
@@ -1,16 +1,21 @@
package org.thoughtcrime.securesms.messagedetails;
+import android.content.Context;
+import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
+import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.RecyclerView;
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.color.MaterialColor;
+import org.thoughtcrime.securesms.database.MmsSmsDatabase;
+import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.messagedetails.MessageDetailsAdapter.MessageDetailsViewState;
import org.thoughtcrime.securesms.messagedetails.MessageDetailsViewModel.Factory;
import org.thoughtcrime.securesms.mms.GlideApp;
@@ -25,10 +30,10 @@ import java.util.List;
public final class MessageDetailsActivity extends PassphraseRequiredActionBarActivity {
- public static final String MESSAGE_ID_EXTRA = "message_id";
- public static final String THREAD_ID_EXTRA = "thread_id";
- public static final String TYPE_EXTRA = "type";
- public static final String RECIPIENT_EXTRA = "recipient_id";
+ private static final String MESSAGE_ID_EXTRA = "message_id";
+ private static final String THREAD_ID_EXTRA = "thread_id";
+ private static final String TYPE_EXTRA = "type";
+ private static final String RECIPIENT_EXTRA = "recipient_id";
private GlideRequests glideRequests;
private MessageDetailsViewModel viewModel;
@@ -36,6 +41,15 @@ public final class MessageDetailsActivity extends PassphraseRequiredActionBarAct
private DynamicTheme dynamicTheme = new DynamicDarkActionBarTheme();
+ public static @NonNull Intent getIntentForMessageDetails(@NonNull Context context, @NonNull MessageRecord message, @NonNull RecipientId recipientId, long threadId) {
+ Intent intent = new Intent(context, MessageDetailsActivity.class);
+ intent.putExtra(MESSAGE_ID_EXTRA, message.getId());
+ intent.putExtra(THREAD_ID_EXTRA, threadId);
+ intent.putExtra(TYPE_EXTRA, message.isMms() ? MmsSmsDatabase.MMS_TRANSPORT : MmsSmsDatabase.SMS_TRANSPORT);
+ intent.putExtra(RECIPIENT_EXTRA, recipientId);
+ return intent;
+ }
+
@Override
protected void onPreCreate() {
dynamicTheme.onCreate(this);
@@ -44,7 +58,7 @@ public final class MessageDetailsActivity extends PassphraseRequiredActionBarAct
@Override
protected void onCreate(Bundle savedInstanceState, boolean ready) {
super.onCreate(savedInstanceState, ready);
- setContentView(R.layout.message_details_2_activity);
+ setContentView(R.layout.message_details_activity);
glideRequests = GlideApp.with(this);
diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsAdapter.java
index 4662fce85..1e4030ae6 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsAdapter.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageDetailsAdapter.java
@@ -32,11 +32,11 @@ final class MessageDetailsAdapter extends ListAdapter new ConfirmIdentityDialog(itemView.getContext(), data.getMessageRecord(), data.getKeyMismatchFailure()).show());
} else if ((data.getNetworkFailure() != null && !data.getMessageRecord().isPending()) || (!data.getMessageRecord().getRecipient().isPushGroup() && data.getMessageRecord().isFailed())) {
timestamp.setVisibility(View.GONE);
error.setVisibility(View.VISIBLE);
conflictButton.setVisibility(View.GONE);
- error.setText(itemView.getContext().getString(R.string.MessageDetailsRecipient_failed_to_send));
+ error.setText(itemView.getContext().getString(R.string.message_details_recipient__failed_to_send));
} else {
timestamp.setVisibility(View.VISIBLE);
error.setVisibility(View.GONE);
diff --git a/app/src/main/res/layout/message_details_2_activity.xml b/app/src/main/res/layout/message_details_2_activity.xml
deleted file mode 100644
index 05004eb82..000000000
--- a/app/src/main/res/layout/message_details_2_activity.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/message_details_2_header.xml b/app/src/main/res/layout/message_details_2_header.xml
deleted file mode 100644
index 1e8fae2b1..000000000
--- a/app/src/main/res/layout/message_details_2_header.xml
+++ /dev/null
@@ -1,189 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/message_details_activity.xml b/app/src/main/res/layout/message_details_activity.xml
index 88cfb1061..05004eb82 100644
--- a/app/src/main/res/layout/message_details_activity.xml
+++ b/app/src/main/res/layout/message_details_activity.xml
@@ -1,14 +1,8 @@
-
-
-
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/message_details_header.xml b/app/src/main/res/layout/message_details_header.xml
index 413ce9132..7602db977 100644
--- a/app/src/main/res/layout/message_details_header.xml
+++ b/app/src/main/res/layout/message_details_header.xml
@@ -1,32 +1,51 @@
-
-
-
-
+
+ android:paddingStart="16dp"
+ android:paddingTop="24dp"
+ android:paddingEnd="16dp"
+ android:paddingBottom="24dp">
+
+
+
+
+
+
+
+
+
+
-
+
+
diff --git a/app/src/main/res/layout/message_details_2_recipient.xml b/app/src/main/res/layout/message_details_recipient.xml
similarity index 70%
rename from app/src/main/res/layout/message_details_2_recipient.xml
rename to app/src/main/res/layout/message_details_recipient.xml
index db85886ef..ee4828b85 100644
--- a/app/src/main/res/layout/message_details_2_recipient.xml
+++ b/app/src/main/res/layout/message_details_recipient.xml
@@ -14,7 +14,7 @@
android:padding="16dp">
+ app:layout_constraintBottom_toTopOf="@+id/message_details_recipient_error_description"/>
-
-
diff --git a/app/src/main/res/layout/message_details_2_recipient_header.xml b/app/src/main/res/layout/message_details_recipient_header.xml
similarity index 100%
rename from app/src/main/res/layout/message_details_2_recipient_header.xml
rename to app/src/main/res/layout/message_details_recipient_header.xml
diff --git a/app/src/main/res/layout/message_recipient_list_item.xml b/app/src/main/res/layout/message_recipient_list_item.xml
deleted file mode 100644
index 4f78627f3..000000000
--- a/app/src/main/res/layout/message_recipient_list_item.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 90d7e83a5..3c929d5f8 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -647,10 +647,6 @@
Learn more
-
- Failed to send
- New safety number
-
Unable to find message
Message from %1$s
@@ -1713,9 +1709,6 @@
Received
Disappears
Via
- To:
- From:
- With:
Pending
@@ -1725,6 +1718,10 @@
Read by
Not sent
+
+ Failed to send
+ New safety number
+
Create passphrase
Select contacts