Verified 1:1 chats, Android UI (#2560)

Depends on https://github.com/deltachat/deltachat-core-rust/pull/4315/.

Follow-up for https://github.com/deltachat/deltachat-android/pull/2541.

- Show a "verified" icon on protection changed update messages
- Add C API
- Show a dialog over the input bar not only for contact requests, but also when the protection is broken (using the new method `isHalfBlocked()`)
  - The positive button reads "OK" (as opposed to contact requests where it reads "Accept")
- Add SVG icons, remove PNG one
- Translations
- When tapping on the `DC_INFO_PROTECTION_{EN|DIS}ABLED` message, show more information (for now, it leads to the online preview of my FAQ PR)
- Block loading remote images in the "Full Msg View" not only for contact requests, also when the protection is broken (using the new method `isHalfBlocked()`)
- Show a big verified/crossed-out-verified symbol over the `DC_INFO_PROTECTION_{EN|DIS}ABLED` messages
- Fix a bug that was kind of present before (for contact requests) but only became really visible now:
  - Set a draft with an image (or other attachment)
  - Your chat partner breaks verification
  - Expected: Both the input bar and the draft image are hidden by the input-bar-dialog.
  - Bug behavior (before c31de5bcf): The input bar is hidden, but the draft image stays visible.
This commit is contained in:
Hocuri
2023-07-14 12:05:05 +02:00
committed by GitHub
parent df5537f0f6
commit 11a2cfbff7
19 changed files with 179 additions and 63 deletions
+5
View File
@@ -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)
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

+8
View File
@@ -0,0 +1,8 @@
<vector android:height="18sp" android:viewportHeight="1304.4"
android:viewportWidth="1325.6" android:width="18sp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffff"
android:pathData="M244.8,233.9L1060.9,233.9A0.1,0.1 0,0 1,1061 233.9L1061,1031.9A0.1,0.1 0,0 1,1060.9 1031.9L244.8,1031.9A0.1,0.1 0,0 1,244.8 1031.9L244.8,233.9A0.1,0.1 0,0 1,244.8 233.9z"
android:strokeColor="#00000000" android:strokeWidth="206.103"/>
<path android:fillColor="#1cc9fc"
android:pathData="M643.6,1303C555.7,1295.1 479.5,1229.9 452.5,1146.8 365.5,1173.3 257.1,1169.4 192.1,1098 135.6,1041.4 126.1,954.9 133.2,879.5 28,840.4 -23.6,710.9 10.9,606.9 31.5,539.3 89.5,491.4 151,461.3 132.5,383.7 109.5,287.3 176.8,208.6 245.9,117.6 351.5,123.1 457,148.5 487.4,54.1 587.2,-8.2 685.1,1.1 768.6,4.6 848,60.7 874.9,140.6c74.6,-12.9 160.9,-20.5 223.1,31.8 50.7,39.9 88.8,99.2 87.8,165.5 0.9,40.1 -11.3,80.4 -17.3,118.5 91,17 150.8,110.4 156,198.8 -1.4,112 -39.9,161.5 -142.2,226.4 -23.1,9.2 -7.6,-23.6 0.1,0.2 15,101.5 -12.8,196.7 -94.3,247 -61.8,38 -138.4,38.2 -207.8,25.9 -31.3,91.2 -125,155 -221.5,149.4 -5.1,0.5 -10.1,-0.7 -15.1,-1.1zM1035.6,509.5 L915.2,385.5 612.9,685.4 411,498.7 289.1,614.8 603.1,931.9Z" android:strokeWidth="1.33333"/>
</vector>
+11
View File
@@ -0,0 +1,11 @@
<vector android:height="18sp" android:viewportHeight="1304.4"
android:viewportWidth="1325.6" android:width="18sp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffff"
android:pathData="M259.8,272.4L1072.6,272.4A0,0 0,0 1,1072.7 272.4L1072.7,1032.2A0,0 0,0 1,1072.6 1032.3L259.8,1032.3A0,0 0,0 1,259.7 1032.2L259.7,272.4A0,0 0,0 1,259.8 272.4z" android:strokeWidth="178.139"/>
<path android:fillColor="#b9b9b9"
android:pathData="M643.6,1303C555.7,1295.1 479.5,1229.9 452.5,1146.8 365.5,1173.3 257.1,1169.4 192.1,1098 135.6,1041.4 126.1,954.9 133.2,879.5 28,840.4 -23.6,710.9 10.9,606.9 31.5,539.3 89.5,491.4 151,461.3 132.5,383.7 109.5,287.3 176.8,208.6 245.9,117.6 351.5,123.1 457,148.5 487.4,54.1 587.2,-8.2 685.1,1.1 768.6,4.6 848,60.7 874.9,140.6c74.6,-12.9 160.9,-20.5 223.1,31.8 50.7,39.9 88.8,99.2 87.8,165.5 0.9,40.1 -11.3,80.4 -17.3,118.5 91,17 150.8,110.4 156,198.8 -1.4,112 -39.9,161.5 -142.2,226.4 -23.1,9.2 -7.6,-23.6 0.1,0.2 15,101.5 -12.8,196.7 -94.3,247 -61.8,38 -138.4,38.2 -207.8,25.9 -31.3,91.2 -125,155 -221.5,149.4 -5.1,0.5 -10.1,-0.7 -15.1,-1.1zM1035.6,509.5 L915.2,385.5 612.9,685.4 411,498.7 289.1,614.8 603.1,931.9Z" android:strokeWidth="1.33333"/>
<path android:fillColor="#00000000"
android:pathData="M64.6,1240 L1265.3,65.5"
android:strokeColor="#ff0c16" android:strokeLineCap="butt"
android:strokeLineJoin="miter" android:strokeWidth="178.139"/>
</vector>
+12 -3
View File
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.ConversationUpdateItem
xmlns:android="http://schemas.android.com/apk/res/android"
<org.thoughtcrime.securesms.ConversationUpdateItem xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/conversation_item_background"
android:focusable="true"
android:gravity="center"
@@ -13,6 +13,15 @@
android:paddingLeft="28dp"
android:paddingRight="28dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/verified_icon"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_gravity="center_vertical"
tools:src="@drawable/ic_verified"
android:padding="7dp"
android:visibility="gone" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -59,7 +68,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginBottom="6dp"
android:tint="?attr/conversation_item_update_text_color"
app:tint="?attr/conversation_item_update_text_color"
android:visibility="gone" />
</LinearLayout>
+1 -1
View File
@@ -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"
+5 -7
View File
@@ -828,12 +828,11 @@
<string name="ephemeral_timer_weeks_by_you">You set disappearing messages timer to %1$s weeks.</string>
<!-- %1$s will be replaced by the number of weeks (always >1) the timer is set to, %2$s will be replaced by name and address of the contact -->
<string name="ephemeral_timer_weeks_by_other">Disappearing messages timer set to %1$s weeks by %2$s.</string>
<string name="protection_enabled_by_you">You enabled chat protection.</string>
<!-- %1$s will be replaced by name and address of the contact -->
<string name="protection_enabled_by_other">Chat protection enabled by %1$s.</string>
<string name="protection_disabled_by_you">You disabled chat protection.</string>
<!-- %1$s will be replaced by name and address of the contact -->
<string name="protection_disabled_by_other">Chat protection disabled by %1$s.</string>
<string name="chat_protection_broken">%1$s sent a message from another device.</string>
<string name="chat_protection_enabled_tap_to_learn_more">Messages are guaranteed to be end-to-end encrypted from now on. Tap to learn more.</string>
<string name="chat_protection_broken_tap_to_learn_more">%1$s sent a message from another device. Tap to learn more.</string>
<string name="chat_protection_broken_explanation">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.</string>
<string name="learn_more">Learn More</string>
<string name="devicemsg_self_deleted">You deleted the \"Saved messages\" chat.\n\n️ To use the \"Saved messages\" feature again, create a new chat with yourself.</string>
<!-- %1$s will be replaced by the amount of storage already used, sth. as '500 MB'. If you want to use a percentage sign, type in two of them, eg. %1$s %% -->
@@ -1070,5 +1069,4 @@
<string name="update_1_38_android">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</string>
<!-- placeholder will be replaced by the URL https://get.delta.chat/#changelogs -->
<string name="update_1_38_ios">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</string>
</resources>
+4
View File
@@ -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
@@ -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);
@@ -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<DcMsg> batchSelected = new HashSet<>();
@@ -44,11 +46,13 @@ public abstract class BaseConversationItem extends LinearLayout
protected void bind(@NonNull DcMsg messageRecord,
@NonNull DcChat dcChat,
@NonNull Set<DcMsg> 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);
}
}
}
@@ -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);
}
}
@@ -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);
}
@@ -104,7 +104,6 @@ public class ConversationItem extends BaseConversationItem
private ViewGroup container;
private Button msgActionButton;
private @NonNull Recipient conversationRecipient;
private @NonNull Stub<ConversationItemThumbnail> mediaThumbnailStub;
private @NonNull Stub<AudioView> audioViewStub;
private @NonNull Stub<DocumentView> 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()) {
@@ -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);
@@ -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;
@@ -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);
}
@@ -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 `&quot;` 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));
}
}
@@ -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);
}
@@ -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> 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);
}
}