diff --git a/jni/dc_wrapper.c b/jni/dc_wrapper.c index 62d92a39b..d55d6c9e4 100644 --- a/jni/dc_wrapper.c +++ b/jni/dc_wrapper.c @@ -1367,6 +1367,11 @@ JNIEXPORT jboolean Java_com_b44t_messenger_DcChat_isProtected(JNIEnv *env, jobje return dc_chat_is_protected(get_dc_chat(env, obj))!=0; } +JNIEXPORT jboolean Java_com_b44t_messenger_DcChat_isProtectionBroken(JNIEnv *env, jobject obj) +{ + return dc_chat_is_protection_broken(get_dc_chat(env, obj))!=0; +} + JNIEXPORT jboolean Java_com_b44t_messenger_DcChat_isSendingLocations(JNIEnv *env, jobject obj) { diff --git a/res/drawable/ic_verified_broken.xml b/res/drawable/ic_verified_broken.xml new file mode 100644 index 000000000..170164366 --- /dev/null +++ b/res/drawable/ic_verified_broken.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/res/layout/conversation_item_update.xml b/res/layout/conversation_item_update.xml index bfdef7e8a..8261c43ca 100644 --- a/res/layout/conversation_item_update.xml +++ b/res/layout/conversation_item_update.xml @@ -1,9 +1,9 @@ - + + diff --git a/res/layout/message_request_bottom_bar.xml b/res/layout/message_request_bottom_bar.xml index a5078f7ba..385ac0eef 100644 --- a/res/layout/message_request_bottom_bar.xml +++ b/res/layout/message_request_bottom_bar.xml @@ -10,7 +10,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="11dp" android:paddingTop="11dp" - android:textSize="14sp" + style="@style/Signal.Text.Body" tools:text="Chat with Alice In Wondeful Wonderland (alice@wonderland.org)?" app:layout_constraintBottom_toTopOf="@id/message_request_block" app:layout_constraintEnd_toEndOf="parent" diff --git a/res/values/strings.xml b/res/values/strings.xml index 6f19cc76c..af6b2f80c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -834,12 +834,13 @@ You set disappearing messages timer to %1$s weeks. Disappearing messages timer set to %1$s weeks by %2$s. - You enabled chat protection. - - Chat protection enabled by %1$s. - You disabled chat protection. - - Chat protection disabled by %1$s. + + %1$s sent a message from another device. + Messages are guaranteed to be end-to-end encrypted from now on. Tap to learn more. + It is now guaranteed that all messages in this chat are end-to-end encrypted.\n\nEnd-to-end encryption keeps messages private between you and your chat partners. Not even your email provider can read them. + %1$s sent a message from another device. Tap to learn more. + End-to-end encryption cannot be guaranteed anymore, likely because %1$s reinstalled Delta Chat or sent a message from another device.\n\nYou may meet them in person and scan their QR Code again to reestablish guaranteed end-to-end encryption. + Learn More You deleted the \"Saved messages\" chat.\n\nℹ️ To use the \"Saved messages\" feature again, create a new chat with yourself. @@ -1075,5 +1076,4 @@ 1.38 is out:\n\n📎 Removed upper size limit of attachments\n\n🗜️ PNG images (screenshots!) are now compressed as well\n\n⌨️ For Devs: Better apps for chats with sendToChat() and importFiles() (What is Webxdc? → https://webxdc.org)\n\n… and more at %1$s 1.38 is out:\n\n🖼🔍 Ever searching for an image and could not remember the chat? Then the \"All Media\" button is yours!\n\n🧹 \"Clear Chat\" from the profiles\n\n📎 Removed upper size limit of attachments\n\n🗜️ PNG images (screenshots!) are now compressed as well\n\n… and more at %1$s - diff --git a/src/com/b44t/messenger/DcChat.java b/src/com/b44t/messenger/DcChat.java index d2c2497e5..e87a407e7 100644 --- a/src/com/b44t/messenger/DcChat.java +++ b/src/com/b44t/messenger/DcChat.java @@ -43,6 +43,7 @@ public class DcChat { public native boolean isDeviceTalk (); public native boolean canSend (); public native boolean isProtected (); + public native boolean isProtectionBroken(); public native boolean isSendingLocations(); public native boolean isMuted (); public native boolean isContactRequest (); @@ -67,6 +68,9 @@ public class DcChat { return canSend() && !isSelfTalk(); } + public boolean isHalfBlocked() { + return isProtectionBroken() || isContactRequest(); + } // working with raw c-data diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 1fba075dd..1600ff2c3 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -1,5 +1,7 @@ package org.thoughtcrime.securesms; +import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_VERIFIED_ONE_ON_ONE_CHATS; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -138,6 +140,10 @@ public class ApplicationContext extends MultiDexApplication { } // /migrating chat backgrounds + for (int accountId : allAccounts) { + dcAccounts.getAccount(accountId).setConfig(CONFIG_VERIFIED_ONE_ON_ONE_CHATS, "1"); + } + // set translations before starting I/O to avoid sending untranslated MDNs (issue #2288) DcHelper.setStockTranslations(this); diff --git a/src/org/thoughtcrime/securesms/BaseConversationItem.java b/src/org/thoughtcrime/securesms/BaseConversationItem.java index 1f615cd2b..415184597 100644 --- a/src/org/thoughtcrime/securesms/BaseConversationItem.java +++ b/src/org/thoughtcrime/securesms/BaseConversationItem.java @@ -17,6 +17,7 @@ import com.b44t.messenger.rpc.Rpc; import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.util.Util; +import org.thoughtcrime.securesms.recipients.Recipient; import java.util.HashSet; import java.util.Set; @@ -33,6 +34,7 @@ public abstract class BaseConversationItem extends LinearLayout protected final Context context; protected final DcContext dcContext; protected final Rpc rpc; + protected Recipient conversationRecipient; protected @NonNull Set batchSelected = new HashSet<>(); @@ -48,11 +50,13 @@ public abstract class BaseConversationItem extends LinearLayout protected void bind(@NonNull DcMsg messageRecord, @NonNull DcChat dcChat, @NonNull Set batchSelected, - boolean pulseHighlight) + boolean pulseHighlight, + @NonNull Recipient conversationRecipient) { this.messageRecord = messageRecord; this.dcChat = dcChat; this.batchSelected = batchSelected; + this.conversationRecipient = conversationRecipient; setInteractionState(messageRecord, pulseHighlight); } @@ -75,7 +79,10 @@ public abstract class BaseConversationItem extends LinearLayout } protected boolean shouldInterceptClicks(DcMsg messageRecord) { - return batchSelected.isEmpty() && (messageRecord.isFailed()); + return batchSelected.isEmpty() + && (messageRecord.isFailed() + || messageRecord.getInfoType() == DcMsg.DC_INFO_PROTECTION_DISABLED + || messageRecord.getInfoType() == DcMsg.DC_INFO_PROTECTION_ENABLED); } protected void onAccessibilityClick() {} @@ -121,6 +128,10 @@ public abstract class BaseConversationItem extends LinearLayout .setPositiveButton(R.string.ok, null) .create(); d.show(); + } else if (messageRecord.getInfoType() == DcMsg.DC_INFO_PROTECTION_DISABLED) { + DcHelper.showVerificationBrokenDialog(context, conversationRecipient.getName()); + } else if (messageRecord.getInfoType() == DcMsg.DC_INFO_PROTECTION_ENABLED) { + DcHelper.showProtectionEnabledDialog(context); } } } diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index 11cd957ea..2a3a0d8c6 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -915,8 +915,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private void setComposePanelVisibility() { if (dcChat.canSend()) { composePanel.setVisibility(View.VISIBLE); + attachmentManager.setHidden(false); } else { composePanel.setVisibility(View.GONE); + attachmentManager.setHidden(true); hideSoftKeyboard(); } } @@ -1611,7 +1613,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } public void initializeContactRequest() { - if (!dcChat.isContactRequest()) { + if (!dcChat.isHalfBlocked()) { messageRequestBottomView.setVisibility(View.GONE); return; } @@ -1622,21 +1624,34 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity messageRequestBottomView.setVisibility(View.GONE); composePanel.setVisibility(View.VISIBLE); }); - messageRequestBottomView.setBlockOnClickListener(v -> { - // avoid showing compose panel on receiving DC_EVENT_CONTACTS_CHANGED for the chat that is no longer a request after blocking - DcHelper.getEventCenter(this).removeObserver(DcContext.DC_EVENT_CONTACTS_CHANGED, this); - dcContext.blockChat(chatId); - Bundle extras = new Bundle(); - extras.putInt(ConversationListFragment.RELOAD_LIST, 1); - handleReturnToConversationList(extras); - }); - if (dcChat.getType() == DcChat.DC_CHAT_TYPE_GROUP) { + if (dcChat.isProtectionBroken()) { + messageRequestBottomView.setBlockText(R.string.more_info_desktop); + String name = dcContext.getContact(recipient.getDcContact().getId()).getDisplayName(); + messageRequestBottomView.setBlockOnClickListener(v -> DcHelper.showVerificationBrokenDialog(this, name)); + + messageRequestBottomView.setQuestion(getString(R.string.chat_protection_broken, name)); + messageRequestBottomView.setAcceptText(R.string.ok); + + } else if (dcChat.getType() == DcChat.DC_CHAT_TYPE_GROUP) { // We don't support blocking groups yet, so offer to delete it instead messageRequestBottomView.setBlockText(R.string.delete); messageRequestBottomView.setBlockOnClickListener(v -> handleDeleteChat()); + messageRequestBottomView.setQuestion(null); + + } else { + messageRequestBottomView.setBlockText(R.string.block); + messageRequestBottomView.setBlockOnClickListener(v -> { + // avoid showing compose panel on receiving DC_EVENT_CONTACTS_CHANGED for the chat that is no longer a request after blocking + DcHelper.getEventCenter(this).removeObserver(DcContext.DC_EVENT_CONTACTS_CHANGED, this); + + dcContext.blockChat(chatId); + Bundle extras = new Bundle(); + extras.putInt(ConversationListFragment.RELOAD_LIST, 1); + handleReturnToConversationList(extras); + }); + messageRequestBottomView.setQuestion(null); } - messageRequestBottomView.setQuestion(null); } } diff --git a/src/org/thoughtcrime/securesms/ConversationFragment.java b/src/org/thoughtcrime/securesms/ConversationFragment.java index 9eca02f0b..aa32e02c8 100644 --- a/src/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationFragment.java @@ -856,7 +856,7 @@ public class ConversationFragment extends MessageSelectorFragment public void onShowFullClicked(DcMsg messageRecord) { Intent intent = new Intent(getActivity(), FullMsgActivity.class); intent.putExtra(FullMsgActivity.MSG_ID_EXTRA, messageRecord.getId()); - intent.putExtra(FullMsgActivity.IS_CONTACT_REQUEST, getListAdapter().getChat().isContactRequest()); + intent.putExtra(FullMsgActivity.BLOCK_LOADING_REMOTE, getListAdapter().getChat().isHalfBlocked()); startActivity(intent); getActivity().overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out); } diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index b600406ce..1aeb85063 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -108,7 +108,6 @@ public class ConversationItem extends BaseConversationItem private ViewGroup container; private Button msgActionButton; - private @NonNull Recipient conversationRecipient; private @NonNull Stub mediaThumbnailStub; private @NonNull Stub audioViewStub; private @NonNull Stub documentViewStub; @@ -170,10 +169,9 @@ public class ConversationItem extends BaseConversationItem @NonNull Recipient recipients, boolean pulseHighlight) { - bind(messageRecord, dcChat, batchSelected, pulseHighlight); + bind(messageRecord, dcChat, batchSelected, pulseHighlight, recipients); this.locale = locale; this.glideRequests = glideRequests; - this.conversationRecipient = recipients; this.showSender = dcChat.isMultiUser() || messageRecord.getOverrideSenderName() != null; if (showSender && !messageRecord.isOutgoing()) { diff --git a/src/org/thoughtcrime/securesms/ConversationUpdateItem.java b/src/org/thoughtcrime/securesms/ConversationUpdateItem.java index 1f5a35daf..6025336e3 100644 --- a/src/org/thoughtcrime/securesms/ConversationUpdateItem.java +++ b/src/org/thoughtcrime/securesms/ConversationUpdateItem.java @@ -27,6 +27,7 @@ public class ConversationUpdateItem extends BaseConversationItem { private DeliveryStatusView deliveryStatusView; private AppCompatImageView appIcon; + private AppCompatImageView verifiedIcon; private int textColor; public ConversationUpdateItem(Context context) { @@ -46,6 +47,7 @@ public class ConversationUpdateItem extends BaseConversationItem bodyText = findViewById(R.id.conversation_update_body); deliveryStatusView = new DeliveryStatusView(findViewById(R.id.delivery_indicator)); appIcon = findViewById(R.id.app_icon); + verifiedIcon = findViewById(R.id.verified_icon); bodyText.setOnLongClickListener(passthroughClickListener); @@ -62,7 +64,7 @@ public class ConversationUpdateItem extends BaseConversationItem @NonNull Recipient conversationRecipient, boolean pulseUpdate) { - bind(messageRecord, dcChat, batchSelected, pulseUpdate); + bind(messageRecord, dcChat, batchSelected, pulseUpdate, conversationRecipient); setGenericInfoRecord(messageRecord); } @@ -87,7 +89,9 @@ public class ConversationUpdateItem extends BaseConversationItem } private void setGenericInfoRecord(DcMsg messageRecord) { - if (messageRecord.getInfoType() == DcMsg.DC_INFO_WEBXDC_INFO_MESSAGE) { + int infoType = messageRecord.getInfoType(); + + if (infoType == DcMsg.DC_INFO_WEBXDC_INFO_MESSAGE) { DcMsg parentMsg = messageRecord.getParent(); // It is possible that we only received an update without the webxdc itself. @@ -108,6 +112,16 @@ public class ConversationUpdateItem extends BaseConversationItem appIcon.setVisibility(GONE); } + if (infoType == DcMsg.DC_INFO_PROTECTION_ENABLED) { + verifiedIcon.setVisibility(VISIBLE); + verifiedIcon.setImageResource(R.drawable.ic_verified); + } else if (infoType == DcMsg.DC_INFO_PROTECTION_DISABLED) { + verifiedIcon.setVisibility(VISIBLE); + verifiedIcon.setImageResource(R.drawable.ic_verified_broken); + } else { + verifiedIcon.setVisibility(GONE); + } + bodyText.setText(messageRecord.getDisplayBody()); bodyText.setVisibility(VISIBLE); diff --git a/src/org/thoughtcrime/securesms/FullMsgActivity.java b/src/org/thoughtcrime/securesms/FullMsgActivity.java index 4cf4f45eb..d5ed6f1e4 100644 --- a/src/org/thoughtcrime/securesms/FullMsgActivity.java +++ b/src/org/thoughtcrime/securesms/FullMsgActivity.java @@ -23,12 +23,12 @@ import java.lang.ref.WeakReference; public class FullMsgActivity extends WebViewActivity { public static final String MSG_ID_EXTRA = "msg_id"; - public static final String IS_CONTACT_REQUEST = "is_contact_request"; + public static final String BLOCK_LOADING_REMOTE = "block_loading_remote"; private int msgId; private DcContext dcContext; private Rpc rpc; private boolean loadRemoteContent = false; - private boolean isContactRequest; + private boolean blockLoadingRemote; enum LoadRemoteContent { NEVER, @@ -40,8 +40,8 @@ public class FullMsgActivity extends WebViewActivity protected void onCreate(Bundle state, boolean ready) { super.onCreate(state, ready); - isContactRequest = getIntent().getBooleanExtra(IS_CONTACT_REQUEST, false); - loadRemoteContent = !isContactRequest && Prefs.getAlwaysLoadRemoteContent(this); + blockLoadingRemote = getIntent().getBooleanExtra(BLOCK_LOADING_REMOTE, false); + loadRemoteContent = !blockLoadingRemote && Prefs.getAlwaysLoadRemoteContent(this); webView.getSettings().setBlockNetworkLoads(!loadRemoteContent); // setBuiltInZoomControls() adds pinch-to-zoom as well as two on-screen zoom control buttons. @@ -128,7 +128,7 @@ public class FullMsgActivity extends WebViewActivity String alwaysCheckmark = ""; String onceCheckmark = ""; String neverCheckmark = ""; - if (!isContactRequest && Prefs.getAlwaysLoadRemoteContent(this)) { + if (!blockLoadingRemote && Prefs.getAlwaysLoadRemoteContent(this)) { alwaysCheckmark = checkmark; } else if (loadRemoteContent) { onceCheckmark = checkmark; @@ -136,10 +136,10 @@ public class FullMsgActivity extends WebViewActivity neverCheckmark = checkmark; } - if (!isContactRequest) { + if (!blockLoadingRemote) { builder.setNeutralButton(alwaysCheckmark + getString(R.string.always), (dialog, which) -> onChangeLoadRemoteContent(LoadRemoteContent.ALWAYS)); } - builder.setNegativeButton(neverCheckmark + getString(isContactRequest? R.string.no : R.string.never), (dialog, which) -> onChangeLoadRemoteContent(LoadRemoteContent.NEVER)); + builder.setNegativeButton(neverCheckmark + getString(blockLoadingRemote ? R.string.no : R.string.never), (dialog, which) -> onChangeLoadRemoteContent(LoadRemoteContent.NEVER)); builder.setPositiveButton(onceCheckmark + getString(R.string.once), (dialog, which) -> onChangeLoadRemoteContent(LoadRemoteContent.ONCE)); builder.show(); @@ -152,13 +152,13 @@ public class FullMsgActivity extends WebViewActivity switch (loadRemoteContent) { case NEVER: this.loadRemoteContent = false; - if (!isContactRequest) { + if (!blockLoadingRemote) { Prefs.setBooleanPreference(this, Prefs.ALWAYS_LOAD_REMOTE_CONTENT, false); } break; case ONCE: this.loadRemoteContent = true; - if (!isContactRequest) { + if (!blockLoadingRemote) { Prefs.setBooleanPreference(this, Prefs.ALWAYS_LOAD_REMOTE_CONTENT, false); } break; diff --git a/src/org/thoughtcrime/securesms/connect/AccountManager.java b/src/org/thoughtcrime/securesms/connect/AccountManager.java index e5598afa6..a149aeacf 100644 --- a/src/org/thoughtcrime/securesms/connect/AccountManager.java +++ b/src/org/thoughtcrime/securesms/connect/AccountManager.java @@ -1,5 +1,7 @@ package org.thoughtcrime.securesms.connect; +import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_VERIFIED_ONE_ON_ONE_CHATS; + import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -31,6 +33,7 @@ public class AccountManager { ApplicationContext appContext = (ApplicationContext)context.getApplicationContext(); appContext.dcContext = appContext.dcAccounts.getSelectedAccount(); DcHelper.setStockTranslations(context); + DcHelper.getContext(context).setConfig(CONFIG_VERIFIED_ONE_ON_ONE_CHATS, "1"); DirectShareUtil.resetAllShortcuts(appContext); } diff --git a/src/org/thoughtcrime/securesms/connect/DcHelper.java b/src/org/thoughtcrime/securesms/connect/DcHelper.java index 79053f700..26c298a9c 100644 --- a/src/org/thoughtcrime/securesms/connect/DcHelper.java +++ b/src/org/thoughtcrime/securesms/connect/DcHelper.java @@ -14,6 +14,7 @@ import android.webkit.MimeTypeMap; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; import androidx.core.content.FileProvider; import com.b44t.messenger.DcAccounts; @@ -30,8 +31,10 @@ import org.thoughtcrime.securesms.ShareActivity; import org.thoughtcrime.securesms.database.model.ThreadRecord; import org.thoughtcrime.securesms.notifications.NotificationCenter; import org.thoughtcrime.securesms.providers.PersistentBlobProvider; +import org.thoughtcrime.securesms.qr.QrActivity; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.FileUtils; +import org.thoughtcrime.securesms.util.IntentUtils; import org.thoughtcrime.securesms.util.MediaUtil; import java.io.File; @@ -74,6 +77,7 @@ public class DcHelper { public static final String CONFIG_SOCKS5_PORT = "socks5_port"; public static final String CONFIG_SOCKS5_USER = "socks5_user"; public static final String CONFIG_SOCKS5_PASSWORD = "socks5_password"; + public static final String CONFIG_VERIFIED_ONE_ON_ONE_CHATS = "verified_one_on_one_chats"; public static DcContext getContext(@NonNull Context context) { return ApplicationContext.getInstance(context).dcContext; @@ -244,6 +248,11 @@ public class DcHelper { dcContext.setStockTranslation(123, context.getString(R.string.aeap_explanation)); dcContext.setStockTranslation(162, context.getString(R.string.multidevice_qr_subtitle)); dcContext.setStockTranslation(163, context.getString(R.string.multidevice_transfer_done_devicemsg)); + + // The next two strings should only be set if the UI actually shows more info when the user clicks on the + // DC_INFO_PROTECTION_{EN|DIS}ABLED info message + dcContext.setStockTranslation(170, context.getString(R.string.chat_protection_enabled_tap_to_learn_more)); + dcContext.setStockTranslation(171, context.getString(R.string.chat_protection_broken_tap_to_learn_more)); } public static File getImexDir() { @@ -438,4 +447,26 @@ public class DcHelper { return context.getString(R.string.connectivity_not_connected); } } + + public static void showVerificationBrokenDialog(Context context, String name) { + new AlertDialog.Builder(context) + .setMessage(context.getString(R.string.chat_protection_broken_explanation, name)) + .setNeutralButton(R.string.learn_more, (d, w) -> IntentUtils.showBrowserIntent(context, "https://staging.delta.chat/684/en/help#verificationbroken")) + .setNegativeButton(R.string.qrscan_title, (d, w) -> context.startActivity(new Intent(context, QrActivity.class))) + .setPositiveButton(R.string.ok, null) + .setCancelable(true) + .show(); + } + + public static void showProtectionEnabledDialog(Context context) { + new AlertDialog.Builder(context) + .setMessage(context.getString(R.string.chat_protection_enabled_explanation)) + .setNeutralButton(R.string.learn_more, (d, w) -> IntentUtils.showBrowserIntent(context, "https://staging.delta.chat/733/en/help#verifiedchats")) + .setNegativeButton(R.string.qrscan_title, (d, w) -> context.startActivity(new Intent(context, QrActivity.class))) + .setPositiveButton(R.string.ok, null) + .setCancelable(true) + .show(); + // One day, it would be nice to point the user to the local help: + //context.startActivity(new Intent(context, LocalHelpActivity.class)); + } } diff --git a/src/org/thoughtcrime/securesms/messagerequests/MessageRequestsBottomView.java b/src/org/thoughtcrime/securesms/messagerequests/MessageRequestsBottomView.java index 360ffa13d..d666d0cce 100644 --- a/src/org/thoughtcrime/securesms/messagerequests/MessageRequestsBottomView.java +++ b/src/org/thoughtcrime/securesms/messagerequests/MessageRequestsBottomView.java @@ -43,6 +43,10 @@ public class MessageRequestsBottomView extends ConstraintLayout { accept.setOnClickListener(acceptOnClickListener); } + public void setAcceptText(int text) { + accept.setText(text); + } + public void setBlockOnClickListener(OnClickListener deleteOnClickListener) { block.setOnClickListener(deleteOnClickListener); } diff --git a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java index 35f7d7aaa..135d67823 100644 --- a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java +++ b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java @@ -99,6 +99,8 @@ public class AttachmentManager { private @NonNull Optional slide = Optional.absent(); private @Nullable Uri imageCaptureUri; private @Nullable Uri videoCaptureUri; + private boolean attachmentPresent; + private boolean hidden; public AttachmentManager(@NonNull Activity activity, @NonNull AttachmentListener listener) { this.context = activity; @@ -136,7 +138,7 @@ public class AttachmentManager { @Override public void onSuccess(Boolean result) { thumbnail.clear(glideRequests); - attachmentViewStub.get().setVisibility(View.GONE); + setAttachmentPresent(false); attachmentListener.onAttachmentChanged(); } @@ -146,7 +148,7 @@ public class AttachmentManager { }); } else { thumbnail.clear(glideRequests); - attachmentViewStub.get().setVisibility(View.GONE); + setAttachmentPresent(false); attachmentListener.onAttachmentChanged(); } @@ -245,7 +247,7 @@ public class AttachmentManager { @Override protected void onPreExecute() { thumbnail.clear(glideRequests); - attachmentViewStub.get().setVisibility(View.VISIBLE); + setAttachmentPresent(true); } @Override @@ -270,19 +272,19 @@ public class AttachmentManager { @Override protected void onPostExecute(@Nullable final Slide slide) { - if (slide == null) { - attachmentViewStub.get().setVisibility(View.GONE); + if (slide == null) { + setAttachmentPresent(false); result.set(false); } else if (slide.getFileSize()>1*1024*1024*1024) { // this is only a rough check, videos and images may be recoded // and the core checks more carefully later. - attachmentViewStub.get().setVisibility(View.GONE); + setAttachmentPresent(false); Log.w(TAG, "File too large."); Toast.makeText(slide.context, "File too large.", Toast.LENGTH_LONG).show(); result.set(false); } else { setSlide(slide); - attachmentViewStub.get().setVisibility(View.VISIBLE); + setAttachmentPresent(true); if (slide.hasAudio()) { class SetDurationListener implements AudioSlidePlayer.Listener { @@ -412,7 +414,7 @@ public class AttachmentManager { } public boolean isAttachmentPresent() { - return attachmentViewStub.resolved() && attachmentViewStub.get().getVisibility() == View.VISIBLE; + return attachmentPresent; } public @NonNull SlideDeck buildSlideDeck() { @@ -695,17 +697,26 @@ public class AttachmentManager { } } - public int getVisibility() { - try { - return attachmentViewStub.get().getVisibility(); - } catch(Exception e) { - return View.GONE; - } + public void setHidden(boolean hidden) { + this.hidden = hidden; + updateVisibility(); } - public void setVisibility(int vis) { - try { - attachmentViewStub.get().setVisibility(vis); - } catch(Exception e) {} + private void setAttachmentPresent(boolean isPresent) { + this.attachmentPresent = isPresent; + updateVisibility(); + } + + private void updateVisibility() { + int vis; + if (attachmentPresent && !hidden) { + vis = View.VISIBLE; + } else { + vis = View.GONE; + } + if (vis == View.GONE && !attachmentViewStub.resolved()) { + return; + } + attachmentViewStub.get().setVisibility(vis); } }