mirror of
https://github.com/deltachat/deltachat-android.git
synced 2025-10-03 09:49:21 +02:00
This commit is contained in:
parent
e2d7f2c3d3
commit
10c4a105bb
8 changed files with 256 additions and 54 deletions
|
@ -5,6 +5,7 @@
|
||||||
* hide superfluous "Show Classic E-mails" advanced setting for chatmail
|
* hide superfluous "Show Classic E-mails" advanced setting for chatmail
|
||||||
* remove mostly non-telling transport addresses when referring to a contact;
|
* remove mostly non-telling transport addresses when referring to a contact;
|
||||||
the contact's profile gives a much better overview
|
the contact's profile gives a much better overview
|
||||||
|
* Disable AEAP to enable us to overhaul some things - there are big changes underway in this area, which will come in a few months
|
||||||
|
|
||||||
## v1.56.1
|
## v1.56.1
|
||||||
2025-03
|
2025-03
|
||||||
|
|
|
@ -118,7 +118,6 @@ public class DcContext {
|
||||||
public native void setStockTranslation (int stockId, String translation);
|
public native void setStockTranslation (int stockId, String translation);
|
||||||
public native String getBlobdir ();
|
public native String getBlobdir ();
|
||||||
public native String getLastError ();
|
public native String getLastError ();
|
||||||
public native void configure ();
|
|
||||||
public native void stopOngoingProcess ();
|
public native void stopOngoingProcess ();
|
||||||
public native int isConfigured ();
|
public native int isConfigured ();
|
||||||
public native boolean open (String passphrase);
|
public native boolean open (String passphrase);
|
||||||
|
|
171
src/main/java/com/b44t/messenger/rpc/EnteredLoginParam.java
Normal file
171
src/main/java/com/b44t/messenger/rpc/EnteredLoginParam.java
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
package com.b44t.messenger.rpc;
|
||||||
|
|
||||||
|
public class EnteredLoginParam {
|
||||||
|
// Email address.
|
||||||
|
private final String addr;
|
||||||
|
|
||||||
|
// Password.
|
||||||
|
private final String password;
|
||||||
|
|
||||||
|
// ============ IMAP settings ============
|
||||||
|
|
||||||
|
// Server hostname or IP address.
|
||||||
|
private final String imapServer;
|
||||||
|
|
||||||
|
// Server port.
|
||||||
|
private final int imapPort;
|
||||||
|
|
||||||
|
// Socket security.
|
||||||
|
private final SocketSecurity imapSecurity;
|
||||||
|
|
||||||
|
// Username.
|
||||||
|
private final String imapUser;
|
||||||
|
|
||||||
|
// ============ SMTP settings ============
|
||||||
|
|
||||||
|
// Server hostname or IP address.
|
||||||
|
private final String smtpServer;
|
||||||
|
|
||||||
|
// Server port.
|
||||||
|
private final int smtpPort;
|
||||||
|
|
||||||
|
// Socket security.
|
||||||
|
private final SocketSecurity smtpSecurity;
|
||||||
|
|
||||||
|
// Username.
|
||||||
|
private final String smtpUser;
|
||||||
|
|
||||||
|
// SMTP Password. Only needs to be specified if different than IMAP password.
|
||||||
|
private final String smtpPassword;
|
||||||
|
|
||||||
|
// TLS options: whether to allow invalid certificates and/or
|
||||||
|
// invalid hostnames
|
||||||
|
private final EnteredCertificateChecks certificateChecks;
|
||||||
|
|
||||||
|
// If true, login via OAUTH2 (not recommended anymore)
|
||||||
|
private final boolean oauth2;
|
||||||
|
|
||||||
|
public EnteredLoginParam(String addr,
|
||||||
|
String password,
|
||||||
|
String imapServer,
|
||||||
|
int imapPort,
|
||||||
|
SocketSecurity imapSecurity,
|
||||||
|
String imapUser,
|
||||||
|
String smtpServer,
|
||||||
|
int smtpPort,
|
||||||
|
SocketSecurity smtpSecurity,
|
||||||
|
String smtpUser,
|
||||||
|
String smtpPassword,
|
||||||
|
EnteredCertificateChecks certificateChecks,
|
||||||
|
boolean oauth2) {
|
||||||
|
this.addr = addr;
|
||||||
|
this.password = password;
|
||||||
|
this.imapServer = imapServer;
|
||||||
|
this.imapPort = imapPort;
|
||||||
|
this.imapSecurity = imapSecurity;
|
||||||
|
this.imapUser = imapUser;
|
||||||
|
this.smtpServer = smtpServer;
|
||||||
|
this.smtpPort = smtpPort;
|
||||||
|
this.smtpSecurity = smtpSecurity;
|
||||||
|
this.smtpUser = smtpUser;
|
||||||
|
this.smtpPassword = smtpPassword;
|
||||||
|
this.certificateChecks = certificateChecks;
|
||||||
|
this.oauth2 = oauth2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddr() {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getImapServer() {
|
||||||
|
return imapServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getImapPort() {
|
||||||
|
return imapPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocketSecurity getImapSecurity() {
|
||||||
|
return imapSecurity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getImapUser() {
|
||||||
|
return imapUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSmtpServer() {
|
||||||
|
return smtpServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSmtpPort() {
|
||||||
|
return smtpPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocketSecurity getSmtpSecurity() {
|
||||||
|
return smtpSecurity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSmtpUser() {
|
||||||
|
return smtpUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSmtpPassword() {
|
||||||
|
return smtpPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnteredCertificateChecks getCertificateChecks() {
|
||||||
|
return certificateChecks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOauth2() {
|
||||||
|
return oauth2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum EnteredCertificateChecks {
|
||||||
|
automatic, strict, acceptInvalidCertificates,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EnteredCertificateChecks certificateChecksFromInt(int position) {
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
return EnteredCertificateChecks.automatic;
|
||||||
|
case 1:
|
||||||
|
return EnteredCertificateChecks.strict;
|
||||||
|
case 2:
|
||||||
|
return EnteredCertificateChecks.acceptInvalidCertificates;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Invalid certificate position: " + position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SocketSecurity {
|
||||||
|
// Unspecified socket security, select automatically.
|
||||||
|
automatic,
|
||||||
|
|
||||||
|
// TLS connection.
|
||||||
|
ssl,
|
||||||
|
|
||||||
|
// STARTTLS connection.
|
||||||
|
starttls,
|
||||||
|
|
||||||
|
// No TLS, plaintext connection.
|
||||||
|
plain,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SocketSecurity socketSecurityFromInt(int position) {
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
return SocketSecurity.automatic;
|
||||||
|
case 1:
|
||||||
|
return SocketSecurity.ssl;
|
||||||
|
case 2:
|
||||||
|
return SocketSecurity.starttls;
|
||||||
|
case 3:
|
||||||
|
return SocketSecurity.plain;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Invalid socketSecurity position: " + position);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
package com.b44t.messenger.rpc;
|
package com.b44t.messenger.rpc;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.b44t.messenger.DcJsonrpcInstance;
|
import com.b44t.messenger.DcJsonrpcInstance;
|
||||||
import com.b44t.messenger.util.concurrent.SettableFuture;
|
import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
@ -8,12 +10,16 @@ import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.qr.QrShowFragment;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
public class Rpc {
|
public class Rpc {
|
||||||
|
private final static String TAG = Rpc.class.getSimpleName();
|
||||||
|
|
||||||
private final Map<Integer, SettableFuture<JsonElement>> requestFutures = new ConcurrentHashMap<>();
|
private final Map<Integer, SettableFuture<JsonElement>> requestFutures = new ConcurrentHashMap<>();
|
||||||
private final DcJsonrpcInstance dcJsonrpcInstance;
|
private final DcJsonrpcInstance dcJsonrpcInstance;
|
||||||
private int requestId = 0;
|
private int requestId = 0;
|
||||||
|
@ -38,7 +44,14 @@ public class Rpc {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.error != null) {
|
if (response.error != null) {
|
||||||
future.setException(new RpcException(response.error.toString()));
|
String message;
|
||||||
|
try {
|
||||||
|
message = response.error.getAsJsonObject().get("message").getAsString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Can't get response error message: " + e);
|
||||||
|
message = response.error.toString();
|
||||||
|
}
|
||||||
|
future.setException(new RpcException(message));
|
||||||
} else if (response.result != null) {
|
} else if (response.result != null) {
|
||||||
future.set(response.result);
|
future.set(response.result);
|
||||||
} else {
|
} else {
|
||||||
|
@ -137,6 +150,14 @@ public class Rpc {
|
||||||
return getResult("add_account").getAsInt();
|
return getResult("add_account").getAsInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addTransportFromQr(int accountId, String qrCode) throws RpcException {
|
||||||
|
getResult("add_transport_from_qr", accountId, qrCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTransport(int accountId, EnteredLoginParam param) throws RpcException {
|
||||||
|
getResult("add_transport", accountId, param);
|
||||||
|
}
|
||||||
|
|
||||||
private static class Request {
|
private static class Request {
|
||||||
private final String jsonrpc = "2.0";
|
private final String jsonrpc = "2.0";
|
||||||
public final String method;
|
public final String method;
|
||||||
|
|
|
@ -32,6 +32,8 @@ import androidx.loader.app.LoaderManager;
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.DcEvent;
|
import com.b44t.messenger.DcEvent;
|
||||||
import com.b44t.messenger.DcLot;
|
import com.b44t.messenger.DcLot;
|
||||||
|
import com.b44t.messenger.rpc.Rpc;
|
||||||
|
import com.b44t.messenger.rpc.RpcException;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.request.target.CustomTarget;
|
import com.bumptech.glide.request.target.CustomTarget;
|
||||||
import com.bumptech.glide.request.transition.Transition;
|
import com.bumptech.glide.request.transition.Transition;
|
||||||
|
@ -408,14 +410,7 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||||
|
|
||||||
if (eventId == DcContext.DC_EVENT_CONFIGURE_PROGRESS) {
|
if (eventId == DcContext.DC_EVENT_CONFIGURE_PROGRESS) {
|
||||||
long progress = event.getData1Int();
|
long progress = event.getData1Int();
|
||||||
if (progress==0/*error/aborted*/) {
|
|
||||||
progressError(event.getData2Str());
|
|
||||||
} else if (progress<1000/*progress in permille*/) {
|
|
||||||
progressUpdate((int)progress);
|
progressUpdate((int)progress);
|
||||||
} else if (progress==1000/*done*/) {
|
|
||||||
DcHelper.getAccounts(this).startIo();
|
|
||||||
progressSuccess();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,14 +494,13 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||||
DcHelper.getEventCenter(this).captureNextError();
|
DcHelper.getEventCenter(this).captureNextError();
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
if (!dcContext.setConfigFromQr(qrCode)) {
|
Rpc rpc = DcHelper.getRpc(this);
|
||||||
Util.runOnMain(() -> {
|
try {
|
||||||
progressError(dcContext.getLastError());
|
rpc.addTransportFromQr(dcContext.getAccountId(), qrCode);
|
||||||
});
|
progressSuccess();
|
||||||
return;
|
} catch (RpcException e) {
|
||||||
|
Util.runOnMain(() -> progressError(e.getMessage()));
|
||||||
}
|
}
|
||||||
DcHelper.getAccounts(this).stopIo();
|
|
||||||
dcContext.configure();
|
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,9 @@ import androidx.constraintlayout.widget.Group;
|
||||||
import com.b44t.messenger.DcContext;
|
import com.b44t.messenger.DcContext;
|
||||||
import com.b44t.messenger.DcEvent;
|
import com.b44t.messenger.DcEvent;
|
||||||
import com.b44t.messenger.DcProvider;
|
import com.b44t.messenger.DcProvider;
|
||||||
|
import com.b44t.messenger.rpc.EnteredLoginParam;
|
||||||
|
import com.b44t.messenger.rpc.Rpc;
|
||||||
|
import com.b44t.messenger.rpc.RpcException;
|
||||||
import com.b44t.messenger.util.concurrent.ListenableFuture;
|
import com.b44t.messenger.util.concurrent.ListenableFuture;
|
||||||
import com.b44t.messenger.util.concurrent.SettableFuture;
|
import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||||
import com.google.android.material.textfield.TextInputEditText;
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
@ -280,19 +283,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
|
|
||||||
if (id == R.id.do_register) {
|
if (id == R.id.do_register) {
|
||||||
String oldAddr = DcHelper.getSelfAddr(this);
|
|
||||||
String newAddr = emailInput.getText().toString();
|
|
||||||
if (!TextUtils.isEmpty(oldAddr)
|
|
||||||
&& !TextUtils.equals(oldAddr.toLowerCase(Locale.ROOT), newAddr.toLowerCase(Locale.ROOT))) {
|
|
||||||
// Tell the user about AEAP if they are about to change their address
|
|
||||||
new AlertDialog.Builder(this)
|
|
||||||
.setMessage(getString(R.string.aeap_explanation, oldAddr, newAddr))
|
|
||||||
.setNegativeButton(R.string.cancel, (d, w) -> {})
|
|
||||||
.setPositiveButton(R.string.perm_continue, (d, w) -> do_register())
|
|
||||||
.show();
|
|
||||||
} else {
|
|
||||||
do_register();
|
do_register();
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
} else if (id == android.R.id.home) {
|
} else if (id == android.R.id.home) {
|
||||||
// handle close button click here
|
// handle close button click here
|
||||||
|
@ -616,9 +607,42 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||||
|
|
||||||
// calling configure() results in
|
// calling configure() results in
|
||||||
// receiving multiple DC_EVENT_CONFIGURE_PROGRESS events
|
// receiving multiple DC_EVENT_CONFIGURE_PROGRESS events
|
||||||
DcHelper.getAccounts(this).stopIo();
|
|
||||||
DcHelper.getEventCenter(this).captureNextError();
|
DcHelper.getEventCenter(this).captureNextError();
|
||||||
DcHelper.getContext(this).configure();
|
|
||||||
|
EnteredLoginParam param = new EnteredLoginParam(
|
||||||
|
getParam(R.id.email_text, true),
|
||||||
|
getParam(R.id.password_text, false),
|
||||||
|
getParam(R.id.imap_server_text, true),
|
||||||
|
Util.objectToInt(getParam(R.id.imap_port_text, true)),
|
||||||
|
EnteredLoginParam.socketSecurityFromInt(imapSecurity.getSelectedItemPosition()),
|
||||||
|
getParam(R.id.imap_login_text, false),
|
||||||
|
getParam(R.id.smtp_server_text, true),
|
||||||
|
Util.objectToInt(getParam(R.id.smtp_port_text, true)),
|
||||||
|
EnteredLoginParam.socketSecurityFromInt(smtpSecurity.getSelectedItemPosition()),
|
||||||
|
getParam(R.id.smtp_login_text, false),
|
||||||
|
getParam(R.id.smtp_password_text, false),
|
||||||
|
EnteredLoginParam.certificateChecksFromInt(certCheck.getSelectedItemPosition()),
|
||||||
|
authMethod.getSelectedItemPosition() == 1
|
||||||
|
);
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
Rpc rpc = DcHelper.getRpc(this);
|
||||||
|
try {
|
||||||
|
rpc.addTransport(DcHelper.getContext(this).getAccountId(), param);
|
||||||
|
DcHelper.getAccounts(this).startIo();
|
||||||
|
DcHelper.getEventCenter(this).endCaptureNextError();
|
||||||
|
progressDialog.dismiss();
|
||||||
|
Intent conversationList = new Intent(getApplicationContext(), ConversationListActivity.class);
|
||||||
|
startActivity(conversationList);
|
||||||
|
finish();
|
||||||
|
} catch (RpcException e) {
|
||||||
|
Util.runOnMain(() -> {
|
||||||
|
DcHelper.getEventCenter(this).endCaptureNextError();
|
||||||
|
progressDialog.dismiss();
|
||||||
|
WelcomeActivity.maybeShowConfigurationError(this, e.getMessage());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setConfig(@IdRes int viewId, String configTarget, boolean doTrim) {
|
private void setConfig(@IdRes int viewId, String configTarget, boolean doTrim) {
|
||||||
|
@ -630,6 +654,15 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||||
DcHelper.getContext(this).setConfig(configTarget, value.isEmpty()? null : value);
|
DcHelper.getContext(this).setConfig(configTarget, value.isEmpty()? null : value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getParam(@IdRes int viewId, boolean doTrim) {
|
||||||
|
TextInputEditText view = findViewById(viewId);
|
||||||
|
String value = view.getText().toString();
|
||||||
|
if(doTrim) {
|
||||||
|
value = value.trim();
|
||||||
|
}
|
||||||
|
return value.isEmpty()? null : value;
|
||||||
|
}
|
||||||
|
|
||||||
private void stopLoginProcess() {
|
private void stopLoginProcess() {
|
||||||
DcHelper.getContext(this).stopOngoingProcess();
|
DcHelper.getContext(this).stopOngoingProcess();
|
||||||
}
|
}
|
||||||
|
@ -637,25 +670,9 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||||
@Override
|
@Override
|
||||||
public void handleEvent(@NonNull DcEvent event) {
|
public void handleEvent(@NonNull DcEvent event) {
|
||||||
if (event.getId()==DcContext.DC_EVENT_CONFIGURE_PROGRESS) {
|
if (event.getId()==DcContext.DC_EVENT_CONFIGURE_PROGRESS) {
|
||||||
long progress = event.getData1Int();
|
long progress = event.getData1Int(); // progress in permille
|
||||||
if (progress==0/*error/aborted*/) {
|
|
||||||
DcHelper.getAccounts(this).startIo(); // start-io is also needed on errors to make previous config work in case of changes
|
|
||||||
DcHelper.getEventCenter(this).endCaptureNextError();
|
|
||||||
progressDialog.dismiss();
|
|
||||||
WelcomeActivity.maybeShowConfigurationError(this, event.getData2Str());
|
|
||||||
}
|
|
||||||
else if (progress<1000/*progress in permille*/) {
|
|
||||||
int percent = (int)progress / 10;
|
int percent = (int)progress / 10;
|
||||||
progressDialog.setMessage(getResources().getString(R.string.one_moment)+String.format(" %d%%", percent));
|
progressDialog.setMessage(getResources().getString(R.string.one_moment)+String.format(" %d%%", percent));
|
||||||
}
|
}
|
||||||
else if (progress==1000/*done*/) {
|
|
||||||
DcHelper.getAccounts(this).startIo();
|
|
||||||
DcHelper.getEventCenter(this).endCaptureNextError();
|
|
||||||
progressDialog.dismiss();
|
|
||||||
Intent conversationList = new Intent(getApplicationContext(), ConversationListActivity.class);
|
|
||||||
startActivity(conversationList);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,7 +237,6 @@ public class DcHelper {
|
||||||
dcContext.setStockTranslation(120, context.getString(R.string.qrshow_join_group_hint).replace("\"", ""));
|
dcContext.setStockTranslation(120, context.getString(R.string.qrshow_join_group_hint).replace("\"", ""));
|
||||||
dcContext.setStockTranslation(121, context.getString(R.string.connectivity_not_connected));
|
dcContext.setStockTranslation(121, context.getString(R.string.connectivity_not_connected));
|
||||||
dcContext.setStockTranslation(122, context.getString(R.string.aeap_addr_changed));
|
dcContext.setStockTranslation(122, context.getString(R.string.aeap_addr_changed));
|
||||||
dcContext.setStockTranslation(123, context.getString(R.string.aeap_explanation));
|
|
||||||
dcContext.setStockTranslation(162, context.getString(R.string.multidevice_qr_subtitle));
|
dcContext.setStockTranslation(162, context.getString(R.string.multidevice_qr_subtitle));
|
||||||
dcContext.setStockTranslation(163, context.getString(R.string.multidevice_transfer_done_devicemsg));
|
dcContext.setStockTranslation(163, context.getString(R.string.multidevice_transfer_done_devicemsg));
|
||||||
|
|
||||||
|
|
|
@ -531,7 +531,7 @@
|
||||||
<string name="send_message">Send Message</string>
|
<string name="send_message">Send Message</string>
|
||||||
<!-- Placeholder %1$s will be replaced by the name of the contact changing their address. Placeholders %2$s and %3$s will be replaced by old/new addresses. -->
|
<!-- Placeholder %1$s will be replaced by the name of the contact changing their address. Placeholders %2$s and %3$s will be replaced by old/new addresses. -->
|
||||||
<string name="aeap_addr_changed">%1$s changed their address from %2$s to %3$s</string>
|
<string name="aeap_addr_changed">%1$s changed their address from %2$s to %3$s</string>
|
||||||
<!-- the explanation is shown (1) as a modal dialog with the buttons "Cancel" and "Continue" as well as (2) as a device message -->
|
<!-- deprecated -->
|
||||||
<string name="aeap_explanation">You changed your email address from %1$s to %2$s.\n\nIf you now send a message to a verified group, contacts there will automatically replace the old with your new address.\n\nIt\'s highly advised to set up your old email provider to forward all emails to your new email address. Otherwise you might miss messages of contacts who did not get your new address yet.</string>
|
<string name="aeap_explanation">You changed your email address from %1$s to %2$s.\n\nIf you now send a message to a verified group, contacts there will automatically replace the old with your new address.\n\nIt\'s highly advised to set up your old email provider to forward all emails to your new email address. Otherwise you might miss messages of contacts who did not get your new address yet.</string>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue