diff --git a/CHANGELOG.md b/CHANGELOG.md index f2db7e7eb..6dd7a22b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Target Android 16 * Change color of links in text messages * Improve edge-to-edge support +* Add the option (opt-in) to send anonymous statistics to Delta Chat's developers * Metadata protection: protect message recipients * Allow to withdraw channel invite links and QR codes * Allow to open externally links clicked inside in-chat apps diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java b/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java index 02f2f1271..3929de365 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java @@ -744,6 +744,9 @@ public class ConversationFragment extends MessageSelectorFragment else if(DozeReminder.isDozeReminderMsg(getContext(), messageRecord)) { DozeReminder.dozeReminderTapped(getContext()); } + else if(StatsSending.isStatsSendingDeviceMsg(getContext(), messageRecord)) { + StatsSending.statsDeviceMsgTapped(getActivity()); + } else if(messageRecord.getInfoType() == DcMsg.DC_INFO_WEBXDC_INFO_MESSAGE) { if (messageRecord.getParent() != null) { // if the parent webxdc message still exists diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationListActivity.java b/src/main/java/org/thoughtcrime/securesms/ConversationListActivity.java index 1076889db..f0fa56c83 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationListActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationListActivity.java @@ -80,6 +80,8 @@ import org.thoughtcrime.securesms.util.SendRelayedMessageUtil; import org.thoughtcrime.securesms.util.StorageUtil; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; +import chat.delta.rpc.types.SecurejoinSource; +import chat.delta.rpc.types.SecurejoinUiPath; import java.util.ArrayList; import java.util.Date; @@ -489,7 +491,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit if (uri.getScheme().equalsIgnoreCase(OPENPGP4FPR) || Util.isInviteURL(uri)) { QrCodeHandler qrCodeHandler = new QrCodeHandler(this); - qrCodeHandler.handleQrData(uri.toString()); + qrCodeHandler.handleQrData(uri.toString(), SecurejoinSource.ExternalLink, null); } } } @@ -571,7 +573,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit case IntentIntegrator.REQUEST_CODE: IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); QrCodeHandler qrCodeHandler = new QrCodeHandler(this); - qrCodeHandler.onScanPerformed(scanResult); + qrCodeHandler.onScanPerformed(scanResult, SecurejoinUiPath.QrIcon); break; default: break; diff --git a/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index c8d46085a..8c451f7c4 100644 --- a/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -344,9 +344,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity DcMsg dcMsg = dcContext.getMsg(mediaItem.msgId); DcChat dcChat = dcContext.getChat(dcMsg.getChatId()); - String text = getResources().getQuantityString( - dcChat.isDeviceTalk() ? R.plurals.ask_delete_messages_simple : R.plurals.ask_delete_messages, - 1, 1); + String text = getResources().getQuantityString(R.plurals.ask_delete_messages,1, 1); int positiveBtnLabel = dcChat.isSelfTalk() ? R.string.delete : R.string.delete_for_me; final int[] messageIds = new int[]{mediaItem.msgId}; diff --git a/src/main/java/org/thoughtcrime/securesms/MessageSelectorFragment.java b/src/main/java/org/thoughtcrime/securesms/MessageSelectorFragment.java index d8513f89f..9f86ecf76 100644 --- a/src/main/java/org/thoughtcrime/securesms/MessageSelectorFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/MessageSelectorFragment.java @@ -76,9 +76,7 @@ public abstract class MessageSelectorFragment canDeleteForAll = false; } - String text = getActivity().getResources().getQuantityString( - dcChat.isDeviceTalk() ? R.plurals.ask_delete_messages_simple : R.plurals.ask_delete_messages, - messageIds.length, messageIds.length); + String text = getActivity().getResources().getQuantityString(R.plurals.ask_delete_messages, messageIds.length, messageIds.length); int positiveBtnLabel = dcChat.isSelfTalk() ? R.string.delete : R.string.delete_for_me; AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity()) diff --git a/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java b/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java index 2421ef92d..628525e37 100644 --- a/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java @@ -39,6 +39,8 @@ import org.thoughtcrime.securesms.qr.QrActivity; import org.thoughtcrime.securesms.qr.QrCodeHandler; import org.thoughtcrime.securesms.util.MailtoUtil; +import chat.delta.rpc.types.SecurejoinUiPath; + /** * Activity container for starting a new conversation. * @@ -137,7 +139,7 @@ public class NewConversationActivity extends ContactSelectionActivity { case IntentIntegrator.REQUEST_CODE: IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); QrCodeHandler qrCodeHandler = new QrCodeHandler(this); - qrCodeHandler.onScanPerformed(scanResult); + qrCodeHandler.onScanPerformed(scanResult, SecurejoinUiPath.NewContact); break; default: break; diff --git a/src/main/java/org/thoughtcrime/securesms/StatsSending.java b/src/main/java/org/thoughtcrime/securesms/StatsSending.java new file mode 100644 index 000000000..4b98dfbc0 --- /dev/null +++ b/src/main/java/org/thoughtcrime/securesms/StatsSending.java @@ -0,0 +1,100 @@ +package org.thoughtcrime.securesms; + +import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_STATS_SENDING; +import static org.thoughtcrime.securesms.connect.DcHelper.openHelp; + +import android.app.Activity; +import android.content.Context; +import android.text.util.Linkify; +import android.widget.TextView; + +import androidx.appcompat.app.AlertDialog; + +import com.b44t.messenger.DcContact; +import com.b44t.messenger.DcContext; +import com.b44t.messenger.DcMsg; + +import org.thoughtcrime.securesms.connect.DcHelper; +import org.thoughtcrime.securesms.util.IntentUtils; +import org.thoughtcrime.securesms.util.Prefs; + +import java.util.Locale; + +public class StatsSending { + /** @noinspection unused: We will start adding a device message once stats-sending is tested a bit */ + public static void maybeAddStatsSendingDeviceMsg(Context context) { + if (Prefs.getStatsDeviceMsgId(context) != 0) { + return; + } + if (DcHelper.getInt(context, CONFIG_STATS_SENDING) != 0) { + return; // Stats-sending is already enabled + } + DcContext dcContext = DcHelper.getContext(context); + DcMsg msg = new DcMsg(dcContext, DcMsg.DC_MSG_TEXT); + msg.setText(context.getString(R.string.stats_device_message)); + int msgId = dcContext.addDeviceMsg("stats_device_message", msg); + if (msgId!=0) { + Prefs.setStatsDeviceMsgId(context, msgId); + } + } + + public static boolean isStatsSendingDeviceMsg(Context context, DcMsg msg) { + return msg != null + && msg.getFromId() == DcContact.DC_CONTACT_ID_DEVICE + && msg.getId() == Prefs.getStatsDeviceMsgId(context); + } + + public static void statsDeviceMsgTapped(Activity activity) { + if (DcHelper.getInt(activity, CONFIG_STATS_SENDING) != 0) { + showStatsDisableDialog(activity); + } else { + showStatsConfirmationDialog(activity, () -> {}); + } + } + + public static void showStatsConfirmationDialog(Activity activity, Runnable onConfigChangedListener) { + AlertDialog d = new AlertDialog.Builder(activity) + .setMessage(R.string.stats_confirmation_dialog) + .setNegativeButton(R.string.cancel, (_d, i) -> {}) + .setPositiveButton(R.string.yes, (_d, i) -> { + DcHelper.set(activity, DcHelper.CONFIG_STATS_SENDING, "1"); + onConfigChangedListener.run(); + showStatsThanksDialog(activity); + }) + .setNeutralButton(R.string.more_info_desktop, (_d, i) -> openHelp(activity, "#statssending")) + .create(); + d.show(); + try { + //noinspection DataFlowIssue + Linkify.addLinks((TextView) d.findViewById(android.R.id.message), Linkify.WEB_URLS); + } catch (NullPointerException e) { + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + } + + private static void showStatsThanksDialog(Activity activity) { + String stats_id = DcHelper.get(activity, DcHelper.CONFIG_STATS_ID); + new AlertDialog.Builder(activity) + .setMessage(R.string.stats_thanks) + .setNeutralButton(R.string.no, (d, i) -> {}) + .setPositiveButton(R.string.yes, (d, i) -> { + String ln = Locale.getDefault().getLanguage(); + IntentUtils.showInBrowser(activity, "https://cispa.qualtrics.com/jfe/form/SV_9YmhkpGa48KxfLg?id=" + stats_id + "&ln=" + ln); + }) + .show(); + } + + public static void showStatsDisableDialog(Activity activity) { + AlertDialog d = new AlertDialog.Builder(activity) + .setMessage(R.string.stats_disable_dialog) + .setNegativeButton(R.string.disable, (_d, i) -> { + DcHelper.set(activity, DcHelper.CONFIG_STATS_SENDING, "0"); + }) + .setPositiveButton(R.string.stats_keep_sending, (_d, i) -> { + }) + .setNeutralButton(R.string.more_info_desktop, (_d, i) -> openHelp(activity, "#statssending")) + .create(); + d.show(); + } +} diff --git a/src/main/java/org/thoughtcrime/securesms/WebViewActivity.java b/src/main/java/org/thoughtcrime/securesms/WebViewActivity.java index b092e3c62..2d97e16c0 100644 --- a/src/main/java/org/thoughtcrime/securesms/WebViewActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/WebViewActivity.java @@ -28,6 +28,8 @@ import org.thoughtcrime.securesms.util.IntentUtils; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; +import chat.delta.rpc.types.SecurejoinSource; + import java.net.IDN; public class WebViewActivity extends PassphraseRequiredActionBarActivity @@ -302,7 +304,7 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity // invite-links should be handled directly String schema = url.split(":")[0].toLowerCase(); if (schema.equals("openpgp4fpr") || url.startsWith("https://" + Util.INVITE_DOMAIN + "/")) { - new QrCodeHandler(this).handleQrData(url); + new QrCodeHandler(this).handleQrData(url, SecurejoinSource.InternalLink, null); return true; // abort internal loading } diff --git a/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java b/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java index e98f468d9..b25bdc5fd 100644 --- a/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java +++ b/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java @@ -61,6 +61,8 @@ public class DcHelper { public static final String CONFIG_PROXY_ENABLED = "proxy_enabled"; public static final String CONFIG_PROXY_URL = "proxy_url"; public static final String CONFIG_PRIVATE_TAG = "private_tag"; + public static final String CONFIG_STATS_SENDING = "stats_sending"; + public static final String CONFIG_STATS_ID = "stats_id"; public static DcContext getContext(@NonNull Context context) { return ApplicationContext.getInstance(context).dcContext; diff --git a/src/main/java/org/thoughtcrime/securesms/contacts/NewContactActivity.java b/src/main/java/org/thoughtcrime/securesms/contacts/NewContactActivity.java index a9b11e960..494c8655a 100644 --- a/src/main/java/org/thoughtcrime/securesms/contacts/NewContactActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/contacts/NewContactActivity.java @@ -22,6 +22,8 @@ import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.qr.QrCodeHandler; import org.thoughtcrime.securesms.util.ViewUtil; +import chat.delta.rpc.types.SecurejoinUiPath; + public class NewContactActivity extends PassphraseRequiredActionBarActivity { @@ -105,7 +107,7 @@ public class NewContactActivity extends PassphraseRequiredActionBarActivity if (requestCode == IntentIntegrator.REQUEST_CODE) { IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); QrCodeHandler qrCodeHandler = new QrCodeHandler(this); - qrCodeHandler.onScanPerformed(scanResult); + qrCodeHandler.onScanPerformed(scanResult, SecurejoinUiPath.NewContact); } } } diff --git a/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java b/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java index 78644a13f..d6abb1244 100644 --- a/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java @@ -5,6 +5,7 @@ import static android.text.InputType.TYPE_TEXT_VARIATION_URI; import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_BCC_SELF; import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_MVBOX_MOVE; import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ONLY_FETCH_MVBOX; +import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_STATS_SENDING; import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SHOW_EMAILS; import android.content.Context; @@ -15,6 +16,7 @@ import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.EditText; +import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; @@ -28,8 +30,10 @@ import org.thoughtcrime.securesms.ApplicationPreferencesActivity; import org.thoughtcrime.securesms.LogViewActivity; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.relay.RelayListActivity; +import org.thoughtcrime.securesms.StatsSending; import org.thoughtcrime.securesms.connect.DcEventCenter; import org.thoughtcrime.securesms.proxy.ProxySettingsActivity; +import org.thoughtcrime.securesms.util.IntentUtils; import org.thoughtcrime.securesms.util.Prefs; import org.thoughtcrime.securesms.util.StreamUtil; import org.thoughtcrime.securesms.util.Util; @@ -48,6 +52,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment private static final String TAG = AdvancedPreferenceFragment.class.getSimpleName(); private ListPreference showEmails; + CheckBoxPreference selfReportingCheckbox; CheckBoxPreference multiDeviceCheckbox; CheckBoxPreference mvboxMoveCheckbox; CheckBoxPreference onlyFetchMvboxCheckbox; @@ -180,6 +185,22 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment }); } + selfReportingCheckbox = this.findPreference("pref_stats_sending"); + if (selfReportingCheckbox != null) { + selfReportingCheckbox.setOnPreferenceChangeListener((preference, newValue) -> { + boolean enabled = (Boolean) newValue; + if (enabled) { + StatsSending.showStatsConfirmationDialog(requireActivity(), () -> { + ((CheckBoxPreference)preference).setChecked(true); + }); + return false; + } else { + dcContext.setConfigInt(CONFIG_STATS_SENDING, 0); + return true; + } + }); + } + Preference proxySettings = this.findPreference("proxy_settings_button"); if (proxySettings != null) { proxySettings.setOnPreferenceClickListener((preference) -> { @@ -215,6 +236,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment showEmails.setValue(value); updateListSummary(showEmails, value); + selfReportingCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_STATS_SENDING)); multiDeviceCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_BCC_SELF)); mvboxMoveCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_MVBOX_MOVE)); onlyFetchMvboxCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_ONLY_FETCH_MVBOX)); diff --git a/src/main/java/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java b/src/main/java/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java index 4360d0ed4..0c5140bbf 100644 --- a/src/main/java/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java @@ -93,7 +93,7 @@ public class ChatsPreferenceFragment extends ListSummaryPreferenceFragment { @Override public void onResume() { super.onResume(); - ((ApplicationPreferencesActivity)getActivity()).getSupportActionBar().setTitle(R.string.pref_chats_and_media); + ((ApplicationPreferencesActivity)getActivity()).getSupportActionBar().setTitle(R.string.pref_chats); String value = Integer.toString(dcContext.getConfigInt(DcHelper.CONFIG_MEDIA_QUALITY)); mediaQuality.setValue(value); diff --git a/src/main/java/org/thoughtcrime/securesms/qr/QrActivity.java b/src/main/java/org/thoughtcrime/securesms/qr/QrActivity.java index 6be2b363e..1b62f61e1 100644 --- a/src/main/java/org/thoughtcrime/securesms/qr/QrActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/qr/QrActivity.java @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.qr; import android.Manifest; import android.app.Activity; +import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; @@ -29,6 +30,8 @@ import com.google.zxing.Result; import com.google.zxing.common.HybridBinarizer; import org.thoughtcrime.securesms.BaseActionBarActivity; +import org.thoughtcrime.securesms.ConversationListActivity; +import org.thoughtcrime.securesms.NewConversationActivity; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.contacts.NewContactActivity; @@ -41,6 +44,9 @@ import org.thoughtcrime.securesms.util.ViewUtil; import java.io.FileNotFoundException; import java.io.InputStream; +import chat.delta.rpc.types.SecurejoinSource; +import chat.delta.rpc.types.SecurejoinUiPath; + public class QrActivity extends BaseActionBarActivity implements View.OnClickListener { private final static String TAG = QrActivity.class.getSimpleName(); @@ -149,7 +155,7 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis AttachmentManager.selectImage(this, REQUEST_CODE_IMAGE); } else if (itemId == R.id.paste) { QrCodeHandler qrCodeHandler = new QrCodeHandler(this); - qrCodeHandler.handleQrData(Util.getTextFromClipboard(this)); + qrCodeHandler.handleQrData(Util.getTextFromClipboard(this), SecurejoinSource.Clipboard, getUiPath()); } return false; @@ -200,7 +206,7 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis try { Result result = reader.decode(bBitmap); QrCodeHandler qrCodeHandler = new QrCodeHandler(this); - qrCodeHandler.handleQrData(result.getText()); + qrCodeHandler.handleQrData(result.getText(), SecurejoinSource.ImageLoaded, getUiPath()); } catch (NotFoundException e) { Log.e(TAG, "decode exception", e); Toast.makeText(this, getString(R.string.qrscan_failed), Toast.LENGTH_LONG).show(); @@ -213,6 +219,21 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis } } + private SecurejoinUiPath getUiPath() { + SecurejoinUiPath uiPath = null; + ComponentName caller = this.getCallingActivity(); + if (caller != null) { + if (caller.getClassName().equals(NewConversationActivity.class.getName())) { + uiPath = SecurejoinUiPath.NewContact; + } else if (caller.getClassName().equals(ConversationListActivity.class.getName()) + // RoutingActivity is an alias for ConversationListActivity + || caller.getClassName().endsWith(".RoutingActivity")) { + uiPath = SecurejoinUiPath.QrIcon; + } + } + return uiPath; + } + @Override public void onClick(View v) { viewPager.setCurrentItem(TAB_SCAN); diff --git a/src/main/java/org/thoughtcrime/securesms/qr/QrCodeHandler.java b/src/main/java/org/thoughtcrime/securesms/qr/QrCodeHandler.java index 46d9e942b..84f3c9fd6 100644 --- a/src/main/java/org/thoughtcrime/securesms/qr/QrCodeHandler.java +++ b/src/main/java/org/thoughtcrime/securesms/qr/QrCodeHandler.java @@ -25,10 +25,22 @@ import org.thoughtcrime.securesms.util.views.ProgressDialog; import chat.delta.rpc.Rpc; import chat.delta.rpc.RpcException; -public class QrCodeHandler { +import chat.delta.rpc.types.SecurejoinSource; +import chat.delta.rpc.types.SecurejoinUiPath; +public class QrCodeHandler { private static final String TAG = QrCodeHandler.class.getSimpleName(); + public static int SECUREJOIN_SOURCE_EXTERNAL_LINK = 1; + public static int SECUREJOIN_SOURCE_INTERNAL_LINK = 2; + public static int SECUREJOIN_SOURCE_CLIPBOARD = 3; + public static int SECUREJOIN_SOURCE_IMAGE_LOADED = 4; + public static int SECUREJOIN_SOURCE_SCAN = 5; + + public static int SECUREJOIN_UIPATH_QR_ICON = 1; + public static int SECUREJOIN_UIPATH_NEW_CONTACT = 2; + + private final Activity activity; private final DcContext dcContext; private final Rpc rpc; @@ -41,15 +53,15 @@ public class QrCodeHandler { accId = dcContext.getAccountId(); } - public void onScanPerformed(IntentResult scanResult) { + public void onScanPerformed(IntentResult scanResult, SecurejoinUiPath uipath) { if (scanResult == null || scanResult.getFormatName() == null) { return; // aborted } - handleQrData(scanResult.getContents()); + handleQrData(scanResult.getContents(), SecurejoinSource.Scan, uipath); } - public void handleQrData(String rawString) { + public void handleQrData(String rawString, SecurejoinSource source, SecurejoinUiPath uiPath) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); final DcLot qrParsed = dcContext.checkQr(rawString); String name = dcContext.getContact(qrParsed.getId()).getDisplayName(); @@ -57,7 +69,7 @@ public class QrCodeHandler { case DcContext.DC_QR_ASK_VERIFYCONTACT: case DcContext.DC_QR_ASK_VERIFYGROUP: case DcContext.DC_QR_ASK_JOIN_BROADCAST: - showVerifyContactOrGroup(activity, builder, rawString, qrParsed, name); + showVerifyContactOrGroup(activity, builder, rawString, qrParsed, name, source, uiPath); break; case DcContext.DC_QR_FPR_WITHOUT_ADDR: @@ -224,7 +236,13 @@ public class QrCodeHandler { }); } - private void showVerifyContactOrGroup(Activity activity, AlertDialog.Builder builder, String qrRawString, DcLot qrParsed, String name) { + private void showVerifyContactOrGroup(Activity activity, + AlertDialog.Builder builder, + String qrRawString, + DcLot qrParsed, + String name, + SecurejoinSource source, + SecurejoinUiPath uipath) { String msg; switch (qrParsed.getState()) { case DcContext.DC_QR_ASK_VERIFYGROUP: @@ -239,17 +257,17 @@ public class QrCodeHandler { } builder.setMessage(msg); builder.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> { - DcHelper.getEventCenter(activity).captureNextError(); - int newChatId = dcContext.joinSecurejoin(qrRawString); - DcHelper.getEventCenter(activity).endCaptureNextError(); + try { + int newChatId = DcHelper.getRpc(activity).secureJoinWithUxInfo(dcContext.getAccountId(), qrRawString, source, uipath); + if (newChatId == 0) throw new Exception("Securejoin failed to create a chat"); - if (newChatId != 0) { Intent intent = new Intent(activity, ConversationActivity.class); intent.putExtra(ConversationActivity.CHAT_ID_EXTRA, newChatId); activity.startActivity(intent); - } else { + } catch (Exception e) { + e.printStackTrace(); AlertDialog.Builder builder1 = new AlertDialog.Builder(activity); - builder1.setMessage(dcContext.getLastError()); + builder1.setMessage(e.getMessage()); builder1.setPositiveButton(android.R.string.ok, null); builder1.create().show(); } diff --git a/src/main/java/org/thoughtcrime/securesms/relay/RelayListActivity.java b/src/main/java/org/thoughtcrime/securesms/relay/RelayListActivity.java index d0ae1859d..bb15e4dfc 100644 --- a/src/main/java/org/thoughtcrime/securesms/relay/RelayListActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/relay/RelayListActivity.java @@ -32,6 +32,8 @@ import java.util.List; import chat.delta.rpc.Rpc; import chat.delta.rpc.RpcException; import chat.delta.rpc.types.EnteredLoginParam; +import chat.delta.rpc.types.SecurejoinSource; +import chat.delta.rpc.types.SecurejoinUiPath; public class RelayListActivity extends BaseActionBarActivity implements RelayListAdapter.OnRelayClickListener, DcEventCenter.DcEventDelegate { @@ -88,7 +90,7 @@ public class RelayListActivity extends BaseActionBarActivity String qrdata = getIntent().getStringExtra(EXTRA_QR_DATA); if (qrdata != null) { QrCodeHandler qrCodeHandler = new QrCodeHandler(this); - qrCodeHandler.handleQrData(qrdata); + qrCodeHandler.handleQrData(qrdata, SecurejoinSource.Unknown, SecurejoinUiPath.Unknown); } } @@ -173,7 +175,7 @@ public class RelayListActivity extends BaseActionBarActivity if (requestCode == IntentIntegrator.REQUEST_CODE) { IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); QrCodeHandler qrCodeHandler = new QrCodeHandler(this); - qrCodeHandler.onScanPerformed(scanResult); + qrCodeHandler.onScanPerformed(scanResult, SecurejoinUiPath.Unknown); } } diff --git a/src/main/java/org/thoughtcrime/securesms/util/LongClickCopySpan.java b/src/main/java/org/thoughtcrime/securesms/util/LongClickCopySpan.java index 7f64ca54f..606bedbeb 100644 --- a/src/main/java/org/thoughtcrime/securesms/util/LongClickCopySpan.java +++ b/src/main/java/org/thoughtcrime/securesms/util/LongClickCopySpan.java @@ -19,6 +19,8 @@ import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.qr.QrCodeHandler; +import chat.delta.rpc.types.SecurejoinSource; + public class LongClickCopySpan extends ClickableSpan { private static final String PREFIX_MAILTO = "mailto:"; private static final String PREFIX_TEL = "tel:"; @@ -80,13 +82,13 @@ public class LongClickCopySpan extends ClickableSpan { } } else if (Util.isInviteURL(url)) { QrCodeHandler qrCodeHandler = new QrCodeHandler((Activity) widget.getContext()); - qrCodeHandler.handleQrData(url); + qrCodeHandler.handleQrData(url, SecurejoinSource.InternalLink, null); } else { Activity activity = (Activity) widget.getContext(); DcContext dcContext = DcHelper.getContext(activity); if (dcContext.checkQr(url).getState() == DcContext.DC_QR_PROXY) { QrCodeHandler qrCodeHandler = new QrCodeHandler(activity); - qrCodeHandler.handleQrData(url); + qrCodeHandler.handleQrData(url, null, null); } else { IntentUtils.showInBrowser(widget.getContext(), url); } diff --git a/src/main/java/org/thoughtcrime/securesms/util/Prefs.java b/src/main/java/org/thoughtcrime/securesms/util/Prefs.java index 4e257d843..52d0d2e3e 100644 --- a/src/main/java/org/thoughtcrime/securesms/util/Prefs.java +++ b/src/main/java/org/thoughtcrime/securesms/util/Prefs.java @@ -12,12 +12,10 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; -import com.b44t.messenger.DcAccounts; import com.b44t.messenger.DcContext; import org.thoughtcrime.securesms.BuildConfig; import org.thoughtcrime.securesms.connect.DcHelper; -import org.thoughtcrime.securesms.notifications.FcmReceiveService; import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference; import java.util.ArrayList; @@ -46,6 +44,7 @@ public class Prefs { public static final String SCREEN_SECURITY_PREF = "pref_screen_security"; private static final String ENTER_SENDS_PREF = "pref_enter_sends"; private static final String PROMPTED_DOZE_MSG_ID_PREF = "pref_prompted_doze_msg_id"; + private static final String STATS_DEVICE_MSG_ID_PREF = "pref_stats_device_msg_id"; public static final String DOZE_ASKED_DIRECTLY = "pref_doze_asked_directly"; public static final String ASKED_FOR_NOTIFICATION_PERMISSION= "pref_asked_for_notification_permission"; private static final String IN_THREAD_NOTIFICATION_PREF = "pref_key_inthread_notifications"; @@ -154,6 +153,14 @@ public class Prefs { return getIntegerPreference(context, PROMPTED_DOZE_MSG_ID_PREF, 0); } + public static void setStatsDeviceMsgId(Context context, int msg_id) { + setIntegerPreference(context, STATS_DEVICE_MSG_ID_PREF, msg_id); + } + + public static int getStatsDeviceMsgId(Context context) { + return getIntegerPreference(context, STATS_DEVICE_MSG_ID_PREF, 0); + } + public static boolean isPushEnabled(Context context) { return BuildConfig.USE_PLAY_SERVICES; } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 17ffd8c43..d4251d01c 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -749,6 +749,7 @@ Sound Silent Privacy + Chats and Media System default @@ -823,8 +824,13 @@ Disable IMAP IDLE Do not use IMAP IDLE extension even if the server supports it. Enabling this option will delay message retrieval, enable it only for testing. Send statistics to Delta Chat\'s developers - The attachment contains anonymous usage statistics, which help us improve Delta Chat. Thank you! - + Do you want to help improve Delta Chat and support research by sending weekly anonymous usage statistics?\n\n👉 Tap here… 👈 + Do you want to help improve Delta Chat and support research by sending weekly anonymous usage statistics? + Thank you! You can always disable the sending at \"Settings -> Advanced\".\n\nDo you additionally have 5 minutes to take part in a scientific study on the security of Delta Chat? + Sending of statistics is already enabled.\n\nDo you want to disable it? + Disable + Keep sending + The attachment contains anonymous usage statistics, which helps us improve Delta Chat. See https://delta.chat/help#statssending for more information. Thank you! Search Results @@ -953,7 +959,7 @@ You deleted the \"Saved messages\" chat.\n\nℹ️ To use the \"Saved messages\" feature again, create a new chat with yourself. - ⚠️ Your provider\'s storage is about to run out: %1$s%% are already used.\n\nYou may not be able to receive messages if storage is full.\n\n👉 Please check if you can delete old data in the provider\'s web interface and consider enabling \"Settings / Chats and Media / Delete Old Messages\". You can check your current storage usage anytime at \"Settings / Connectivity\". + ⚠️ Your provider\'s storage is about to run out: %1$s%% are already used.\n\nYou may not be able to receive messages if storage is full.\n\n👉 Please check if you can delete old data in the provider\'s web interface and consider enabling \"Settings / Chats / Delete Old Messages\". You can check your current storage usage anytime at \"Settings / Connectivity\". ⚠️ Date or time on your device seems to be inaccurate (%1$s).\n\nAdjust your clock ⏰🔧 to ensure your messages are received correctly. ⚠️ Your Delta Chat version might be outdated.\n\nThis may cause problems because your chat partners use newer versions - and you are missing the latest features 😳\nPlease check https://get.delta.chat or your app store for updates. diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index e09faabed..be94c2100 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -6,7 +6,7 @@ android:key="preference_category_profile"/> diff --git a/src/main/res/xml/preferences_advanced.xml b/src/main/res/xml/preferences_advanced.xml index c5e3b8af8..7a1a8dad3 100644 --- a/src/main/res/xml/preferences_advanced.xml +++ b/src/main/res/xml/preferences_advanced.xml @@ -49,6 +49,10 @@ +