diff --git a/jni/dc_wrapper.c b/jni/dc_wrapper.c index 9d25ef687..01d01f21d 100644 --- a/jni/dc_wrapper.c +++ b/jni/dc_wrapper.c @@ -1377,6 +1377,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-xhdpi/ic_verified.png b/res/drawable-xhdpi/ic_verified.png deleted file mode 100644 index b95c6f6a5..000000000 Binary files a/res/drawable-xhdpi/ic_verified.png and /dev/null differ diff --git a/res/drawable/ic_verified.xml b/res/drawable/ic_verified.xml new file mode 100644 index 000000000..a92c98538 --- /dev/null +++ b/res/drawable/ic_verified.xml @@ -0,0 +1,8 @@ + + + + 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 baf6ad48f..a56efdb11 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -828,12 +828,11 @@ 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. + %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. @@ -1070,5 +1069,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 68530702c..4b4522a39 100644 --- a/src/com/b44t/messenger/DcChat.java +++ b/src/com/b44t/messenger/DcChat.java @@ -39,6 +39,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 (); @@ -63,6 +64,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 da89d35a4..98227cc7f 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; @@ -127,6 +129,10 @@ public class ApplicationContext extends MultiDexApplication { rpc.start(); + 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 f9fa5b2d7..6d0d36e38 100644 --- a/src/org/thoughtcrime/securesms/BaseConversationItem.java +++ b/src/org/thoughtcrime/securesms/BaseConversationItem.java @@ -15,6 +15,7 @@ import com.b44t.messenger.DcContext; import com.b44t.messenger.DcMsg; import org.thoughtcrime.securesms.connect.DcHelper; +import org.thoughtcrime.securesms.recipients.Recipient; import java.util.HashSet; import java.util.Set; @@ -30,6 +31,7 @@ public abstract class BaseConversationItem extends LinearLayout protected final Context context; protected final DcContext dcContext; + protected Recipient conversationRecipient; protected @NonNull Set batchSelected = new HashSet<>(); @@ -44,11 +46,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); } @@ -71,7 +75,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 class PassthroughClickListener implements View.OnLongClickListener, View.OnClickListener { @@ -112,6 +119,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 cf39f3da3..f4bab9917 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -942,8 +942,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(); } } @@ -1632,7 +1634,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } public void initializeContactRequest() { - if (!dcChat.isContactRequest()) { + if (!dcChat.isHalfBlocked()) { messageRequestBottomView.setVisibility(View.GONE); return; } @@ -1643,21 +1645,33 @@ 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); + messageRequestBottomView.setBlockOnClickListener(v -> DcHelper.showVerificationBrokenDialog(this, recipient.getName())); + + messageRequestBottomView.setQuestion(getString(R.string.chat_protection_broken, recipient.getName())); + 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 b0460d088..879e24704 100644 --- a/src/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationFragment.java @@ -857,7 +857,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 f49a9923a..4ceac173d 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -104,7 +104,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; @@ -166,10 +165,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 99fea57fb..6025336e3 100644 --- a/src/org/thoughtcrime/securesms/ConversationUpdateItem.java +++ b/src/org/thoughtcrime/securesms/ConversationUpdateItem.java @@ -9,7 +9,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatImageView; import android.util.AttributeSet; -import android.widget.TextView; import com.b44t.messenger.DcChat; import com.b44t.messenger.DcMsg; @@ -28,6 +27,7 @@ public class ConversationUpdateItem extends BaseConversationItem { private DeliveryStatusView deliveryStatusView; private AppCompatImageView appIcon; + private AppCompatImageView verifiedIcon; private int textColor; public ConversationUpdateItem(Context context) { @@ -47,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); @@ -63,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); } @@ -88,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. @@ -109,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 edd84f6eb..9a04e2f14 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 8371268c3..fab0c753b 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; @@ -32,6 +34,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 9f899b340..0eda9e2e3 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; @@ -25,12 +26,15 @@ import com.b44t.messenger.rpc.Rpc; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.BuildConfig; +import org.thoughtcrime.securesms.LocalHelpActivity; import org.thoughtcrime.securesms.R; 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.IntentUtils; import org.thoughtcrime.securesms.util.MediaUtil; import java.io.File; @@ -73,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; @@ -233,10 +238,6 @@ public class DcHelper { dcContext.setStockTranslation(155, context.getString(R.string.ephemeral_timer_days_by_other)); dcContext.setStockTranslation(156, context.getString(R.string.ephemeral_timer_weeks_by_you)); dcContext.setStockTranslation(157, context.getString(R.string.ephemeral_timer_weeks_by_other)); - dcContext.setStockTranslation(158, context.getString(R.string.protection_enabled_by_you)); - dcContext.setStockTranslation(159, context.getString(R.string.protection_enabled_by_other)); - dcContext.setStockTranslation(160, context.getString(R.string.protection_disabled_by_you)); - dcContext.setStockTranslation(161, context.getString(R.string.protection_disabled_by_other)); // HACK: svg does not handle entities correctly and shows `"` as the text `quot;`. // until that is fixed, we fix the most obvious errors (core uses encode_minimal, so this does not affect so many characters) @@ -247,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() { @@ -435,4 +441,20 @@ 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")) + .setPositiveButton(R.string.qrscan_title, (d, w) -> context.startActivity(new Intent(context, QrActivity.class))) + .setNegativeButton(R.string.ok, (d, w) -> {}) + .setCancelable(true) + .show(); + } + + public static void showProtectionEnabledDialog(Context context) { + IntentUtils.showBrowserIntent(context, "https://staging.delta.chat/684/en/help#whatdoesverifiedmean"); + // 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 e68530b93..b57eb607d 100644 --- a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java +++ b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java @@ -65,7 +65,6 @@ import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.providers.PersistentBlobProvider; import org.thoughtcrime.securesms.scribbles.ScribbleActivity; import org.thoughtcrime.securesms.util.MediaUtil; -import org.thoughtcrime.securesms.util.StorageUtil; import org.thoughtcrime.securesms.util.ThemeUtil; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.guava.Optional; @@ -99,6 +98,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 +137,7 @@ public class AttachmentManager { @Override public void onSuccess(Boolean result) { thumbnail.clear(glideRequests); - attachmentViewStub.get().setVisibility(View.GONE); + setAttachmentPresent(false); attachmentListener.onAttachmentChanged(); } @@ -146,7 +147,7 @@ public class AttachmentManager { }); } else { thumbnail.clear(glideRequests); - attachmentViewStub.get().setVisibility(View.GONE); + setAttachmentPresent(false); attachmentListener.onAttachmentChanged(); } @@ -245,7 +246,7 @@ public class AttachmentManager { @Override protected void onPreExecute() { thumbnail.clear(glideRequests); - attachmentViewStub.get().setVisibility(View.VISIBLE); + setAttachmentPresent(true); } @Override @@ -270,19 +271,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 +413,7 @@ public class AttachmentManager { } public boolean isAttachmentPresent() { - return attachmentViewStub.resolved() && attachmentViewStub.get().getVisibility() == View.VISIBLE; + return attachmentPresent; } public @NonNull SlideDeck buildSlideDeck() { @@ -666,17 +667,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); } }