mirror of https://github.com/M66B/FairEmail.git
Experiment: identity/linked contact
This commit is contained in:
parent
0d883b50c8
commit
fed1994b23
File diff suppressed because it is too large
Load Diff
|
@ -68,7 +68,7 @@ import javax.mail.internet.InternetAddress;
|
||||||
// https://developer.android.com/topic/libraries/architecture/room.html
|
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
version = 276,
|
version = 277,
|
||||||
entities = {
|
entities = {
|
||||||
EntityIdentity.class,
|
EntityIdentity.class,
|
||||||
EntityAccount.class,
|
EntityAccount.class,
|
||||||
|
@ -2793,6 +2793,12 @@ public abstract class DB extends RoomDatabase {
|
||||||
logMigration(startVersion, endVersion);
|
logMigration(startVersion, endVersion);
|
||||||
db.execSQL("ALTER TABLE `log` ADD COLUMN `thread` INTEGER");
|
db.execSQL("ALTER TABLE `log` ADD COLUMN `thread` INTEGER");
|
||||||
}
|
}
|
||||||
|
}).addMigrations(new Migration(276, 277) {
|
||||||
|
@Override
|
||||||
|
public void migrate(@NonNull SupportSQLiteDatabase db) {
|
||||||
|
logMigration(startVersion, endVersion);
|
||||||
|
db.execSQL("ALTER TABLE `identity` ADD COLUMN `uri` TEXT");
|
||||||
|
}
|
||||||
}).addMigrations(new Migration(998, 999) {
|
}).addMigrations(new Migration(998, 999) {
|
||||||
@Override
|
@Override
|
||||||
public void migrate(@NonNull SupportSQLiteDatabase db) {
|
public void migrate(@NonNull SupportSQLiteDatabase db) {
|
||||||
|
|
|
@ -74,6 +74,8 @@ public class EntityAttachment {
|
||||||
static final Integer SMIME_SIGNED_DATA = 7;
|
static final Integer SMIME_SIGNED_DATA = 7;
|
||||||
static final Integer SMIME_CONTENT = 8;
|
static final Integer SMIME_CONTENT = 8;
|
||||||
|
|
||||||
|
static final String VCARD_PREFIX = BuildConfig.APPLICATION_ID + ".vcard.";
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
public Long id;
|
public Long id;
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|
|
@ -108,6 +108,7 @@ public class EntityIdentity {
|
||||||
public String cc;
|
public String cc;
|
||||||
public String bcc;
|
public String bcc;
|
||||||
public String internal;
|
public String internal;
|
||||||
|
public String uri; // linked contact
|
||||||
@NonNull
|
@NonNull
|
||||||
public Boolean unicode = false;
|
public Boolean unicode = false;
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -228,6 +229,7 @@ public class EntityIdentity {
|
||||||
json.put("cc", cc);
|
json.put("cc", cc);
|
||||||
json.put("bcc", bcc);
|
json.put("bcc", bcc);
|
||||||
json.put("internal", internal);
|
json.put("internal", internal);
|
||||||
|
json.put("uri", uri);
|
||||||
|
|
||||||
json.put("unicode", unicode);
|
json.put("unicode", unicode);
|
||||||
json.put("octetmime", octetmime);
|
json.put("octetmime", octetmime);
|
||||||
|
@ -310,6 +312,8 @@ public class EntityIdentity {
|
||||||
identity.bcc = json.getString("bcc");
|
identity.bcc = json.getString("bcc");
|
||||||
if (json.has("internal") && !json.isNull("internal"))
|
if (json.has("internal") && !json.isNull("internal"))
|
||||||
identity.internal = json.getString("internal");
|
identity.internal = json.getString("internal");
|
||||||
|
if (json.has("uri") && !json.isNull("uri"))
|
||||||
|
identity.uri = json.getString("uri");
|
||||||
|
|
||||||
if (json.has("unicode"))
|
if (json.has("unicode"))
|
||||||
identity.unicode = json.getBoolean("unicode");
|
identity.unicode = json.getBoolean("unicode");
|
||||||
|
@ -366,6 +370,7 @@ public class EntityIdentity {
|
||||||
Objects.equals(i1.cc, other.cc) &&
|
Objects.equals(i1.cc, other.cc) &&
|
||||||
Objects.equals(i1.bcc, other.bcc) &&
|
Objects.equals(i1.bcc, other.bcc) &&
|
||||||
Objects.equals(i1.internal, other.internal) &&
|
Objects.equals(i1.internal, other.internal) &&
|
||||||
|
Objects.equals(i1.uri, other.uri) &&
|
||||||
Objects.equals(i1.unicode, other.unicode) &&
|
Objects.equals(i1.unicode, other.unicode) &&
|
||||||
Objects.equals(i1.octetmime, other.octetmime) &&
|
Objects.equals(i1.octetmime, other.octetmime) &&
|
||||||
// plain_only
|
// plain_only
|
||||||
|
|
|
@ -31,6 +31,7 @@ import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.provider.ContactsContract;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
@ -120,6 +121,8 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
private EditText etCc;
|
private EditText etCc;
|
||||||
private EditText etBcc;
|
private EditText etBcc;
|
||||||
private EditText etInternal;
|
private EditText etInternal;
|
||||||
|
private Button btnUri;
|
||||||
|
private TextView tvUri;
|
||||||
private CheckBox cbSignDefault;
|
private CheckBox cbSignDefault;
|
||||||
private CheckBox cbEncryptDefault;
|
private CheckBox cbEncryptDefault;
|
||||||
private CheckBox cbUnicode;
|
private CheckBox cbUnicode;
|
||||||
|
@ -153,6 +156,7 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
private static final int REQUEST_SAVE = 2;
|
private static final int REQUEST_SAVE = 2;
|
||||||
private static final int REQUEST_DELETE = 3;
|
private static final int REQUEST_DELETE = 3;
|
||||||
private static final int REQUEST_SIGNATURE = 4;
|
private static final int REQUEST_SIGNATURE = 4;
|
||||||
|
private static final int REQUEST_URI = 5;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -220,6 +224,8 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
etCc = view.findViewById(R.id.etCc);
|
etCc = view.findViewById(R.id.etCc);
|
||||||
etBcc = view.findViewById(R.id.etBcc);
|
etBcc = view.findViewById(R.id.etBcc);
|
||||||
etInternal = view.findViewById(R.id.etInternal);
|
etInternal = view.findViewById(R.id.etInternal);
|
||||||
|
btnUri = view.findViewById(R.id.btnUri);
|
||||||
|
tvUri = view.findViewById(R.id.tvUri);
|
||||||
cbSignDefault = view.findViewById(R.id.cbSignDefault);
|
cbSignDefault = view.findViewById(R.id.cbSignDefault);
|
||||||
cbEncryptDefault = view.findViewById(R.id.cbEncryptDefault);
|
cbEncryptDefault = view.findViewById(R.id.cbEncryptDefault);
|
||||||
cbUnicode = view.findViewById(R.id.cbUnicode);
|
cbUnicode = view.findViewById(R.id.cbUnicode);
|
||||||
|
@ -481,6 +487,15 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
btnUri.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent pick = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
|
||||||
|
pick.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
startActivityForResult(Helper.getChooser(getContext(), pick), REQUEST_URI);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
cbEncryptDefault.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
cbEncryptDefault.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
@ -527,6 +542,10 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
cbInsecure.setVisibility(View.GONE);
|
cbInsecure.setVisibility(View.GONE);
|
||||||
|
|
||||||
btnAdvanced.setVisibility(View.GONE);
|
btnAdvanced.setVisibility(View.GONE);
|
||||||
|
if (!BuildConfig.DEBUG) {
|
||||||
|
Helper.hide(btnUri);
|
||||||
|
Helper.hide(tvUri);
|
||||||
|
}
|
||||||
|
|
||||||
etEhlo.setHint(EmailService.getDefaultEhlo());
|
etEhlo.setHint(EmailService.getDefaultEhlo());
|
||||||
|
|
||||||
|
@ -710,6 +729,7 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
args.putString("cc", etCc.getText().toString().trim());
|
args.putString("cc", etCc.getText().toString().trim());
|
||||||
args.putString("bcc", etBcc.getText().toString().trim());
|
args.putString("bcc", etBcc.getText().toString().trim());
|
||||||
args.putString("internal", etInternal.getText().toString().replaceAll(" ", ""));
|
args.putString("internal", etInternal.getText().toString().replaceAll(" ", ""));
|
||||||
|
args.putString("uri", tvUri.getText().toString());
|
||||||
args.putBoolean("sign_default", cbSignDefault.isChecked());
|
args.putBoolean("sign_default", cbSignDefault.isChecked());
|
||||||
args.putBoolean("encrypt_default", cbEncryptDefault.isChecked());
|
args.putBoolean("encrypt_default", cbEncryptDefault.isChecked());
|
||||||
args.putBoolean("unicode", cbUnicode.isChecked());
|
args.putBoolean("unicode", cbUnicode.isChecked());
|
||||||
|
@ -794,6 +814,7 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
String cc = args.getString("cc");
|
String cc = args.getString("cc");
|
||||||
String bcc = args.getString("bcc");
|
String bcc = args.getString("bcc");
|
||||||
String internal = args.getString("internal");
|
String internal = args.getString("internal");
|
||||||
|
String uri = args.getString("uri");
|
||||||
boolean sign_default = args.getBoolean("sign_default");
|
boolean sign_default = args.getBoolean("sign_default");
|
||||||
boolean encrypt_default = args.getBoolean("encrypt_default");
|
boolean encrypt_default = args.getBoolean("encrypt_default");
|
||||||
boolean unicode = args.getBoolean("unicode");
|
boolean unicode = args.getBoolean("unicode");
|
||||||
|
@ -856,6 +877,9 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
if (TextUtils.isEmpty(internal))
|
if (TextUtils.isEmpty(internal))
|
||||||
internal = null;
|
internal = null;
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(uri))
|
||||||
|
uri = null;
|
||||||
|
|
||||||
if (TextUtils.isEmpty(display))
|
if (TextUtils.isEmpty(display))
|
||||||
display = null;
|
display = null;
|
||||||
|
|
||||||
|
@ -949,6 +973,8 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
return true;
|
return true;
|
||||||
if (!Objects.equals(identity.internal, internal))
|
if (!Objects.equals(identity.internal, internal))
|
||||||
return true;
|
return true;
|
||||||
|
if (!Objects.equals(identity.uri, uri))
|
||||||
|
return true;
|
||||||
if (!Objects.equals(identity.sign_default, sign_default))
|
if (!Objects.equals(identity.sign_default, sign_default))
|
||||||
return true;
|
return true;
|
||||||
if (!Objects.equals(identity.encrypt_default, encrypt_default))
|
if (!Objects.equals(identity.encrypt_default, encrypt_default))
|
||||||
|
@ -1052,6 +1078,7 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
identity.cc = cc;
|
identity.cc = cc;
|
||||||
identity.bcc = bcc;
|
identity.bcc = bcc;
|
||||||
identity.internal = internal;
|
identity.internal = internal;
|
||||||
|
identity.uri = uri;
|
||||||
identity.sign_default = sign_default;
|
identity.sign_default = sign_default;
|
||||||
identity.encrypt_default = encrypt_default;
|
identity.encrypt_default = encrypt_default;
|
||||||
identity.unicode = unicode;
|
identity.unicode = unicode;
|
||||||
|
@ -1238,6 +1265,7 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
etCc.setText(identity == null ? null : identity.cc);
|
etCc.setText(identity == null ? null : identity.cc);
|
||||||
etBcc.setText(identity == null ? null : identity.bcc);
|
etBcc.setText(identity == null ? null : identity.bcc);
|
||||||
etInternal.setText(identity == null ? null : identity.internal);
|
etInternal.setText(identity == null ? null : identity.internal);
|
||||||
|
tvUri.setText(identity == null ? null : identity.uri);
|
||||||
cbSignDefault.setChecked(identity != null && identity.sign_default);
|
cbSignDefault.setChecked(identity != null && identity.sign_default);
|
||||||
cbEncryptDefault.setChecked(identity != null && identity.encrypt_default);
|
cbEncryptDefault.setChecked(identity != null && identity.encrypt_default);
|
||||||
cbUnicode.setChecked(identity != null && identity.unicode);
|
cbUnicode.setChecked(identity != null && identity.unicode);
|
||||||
|
@ -1444,6 +1472,9 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
if (resultCode == RESULT_OK && data != null)
|
if (resultCode == RESULT_OK && data != null)
|
||||||
onHtml(data.getExtras());
|
onHtml(data.getExtras());
|
||||||
break;
|
break;
|
||||||
|
case REQUEST_URI:
|
||||||
|
onPickUri(resultCode == RESULT_OK ? data : null);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
Log.e(ex);
|
Log.e(ex);
|
||||||
|
@ -1488,4 +1519,9 @@ public class FragmentIdentity extends FragmentBase {
|
||||||
private void onHtml(Bundle args) {
|
private void onHtml(Bundle args) {
|
||||||
signature = args.getString("html");
|
signature = args.getString("html");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onPickUri(Intent intent) {
|
||||||
|
Uri uri = (intent == null ? null : intent.getData());
|
||||||
|
tvUri.setText(uri == null ? null : uri.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,15 @@ package eu.faircode.email;
|
||||||
import static android.system.OsConstants.ENOSPC;
|
import static android.system.OsConstants.ENOSPC;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.database.Cursor;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
|
import android.provider.ContactsContract;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -148,6 +151,11 @@ import biweekly.Biweekly;
|
||||||
import biweekly.ICalendar;
|
import biweekly.ICalendar;
|
||||||
import biweekly.component.VEvent;
|
import biweekly.component.VEvent;
|
||||||
import biweekly.property.Method;
|
import biweekly.property.Method;
|
||||||
|
import ezvcard.VCard;
|
||||||
|
import ezvcard.VCardVersion;
|
||||||
|
import ezvcard.io.text.VCardWriter;
|
||||||
|
import ezvcard.parameter.AddressType;
|
||||||
|
import ezvcard.parameter.TelephoneType;
|
||||||
|
|
||||||
public class MessageHelper {
|
public class MessageHelper {
|
||||||
private boolean ensuredEnvelope = false;
|
private boolean ensuredEnvelope = false;
|
||||||
|
@ -1025,6 +1033,7 @@ public class MessageHelper {
|
||||||
reply.removeAttr("fairemail");
|
reply.removeAttr("fairemail");
|
||||||
|
|
||||||
DB db = DB.getInstance(context);
|
DB db = DB.getInstance(context);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
|
|
||||||
|
@ -1079,6 +1088,161 @@ public class MessageHelper {
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
VCard vcard = null;
|
||||||
|
|
||||||
|
if (identity.uri != null &&
|
||||||
|
Helper.hasPermission(context, Manifest.permission.READ_CONTACTS)) {
|
||||||
|
vcard = new VCard();
|
||||||
|
vcard.addEmail(identity.email);
|
||||||
|
if (!TextUtils.isEmpty(identity.name))
|
||||||
|
vcard.setFormattedName(identity.name);
|
||||||
|
|
||||||
|
ContentResolver resolver = context.getContentResolver();
|
||||||
|
try (Cursor cursor = resolver.query(Uri.parse(identity.uri),
|
||||||
|
new String[]{
|
||||||
|
ContactsContract.Contacts._ID
|
||||||
|
}, null, null, null)) {
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
String contactId = cursor.getString(0);
|
||||||
|
|
||||||
|
try (Cursor address = resolver.query(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI,
|
||||||
|
new String[]{
|
||||||
|
ContactsContract.CommonDataKinds.StructuredPostal.TYPE,
|
||||||
|
ContactsContract.CommonDataKinds.StructuredPostal.STREET,
|
||||||
|
ContactsContract.CommonDataKinds.StructuredPostal.POBOX,
|
||||||
|
ContactsContract.CommonDataKinds.StructuredPostal.CITY,
|
||||||
|
ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE,
|
||||||
|
ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY,
|
||||||
|
ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS,
|
||||||
|
},
|
||||||
|
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
|
||||||
|
new String[]{contactId}, null)) {
|
||||||
|
while (address.moveToNext()) {
|
||||||
|
int type = address.getInt(0);
|
||||||
|
if (type != ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME &&
|
||||||
|
type != ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ezvcard.property.Address a = new ezvcard.property.Address();
|
||||||
|
if (!address.isNull(1))
|
||||||
|
a.setStreetAddress(address.getString(1));
|
||||||
|
if (!address.isNull(2))
|
||||||
|
a.setPoBox(address.getString(2));
|
||||||
|
if (!address.isNull(3))
|
||||||
|
a.setLocality(address.getString(3));
|
||||||
|
if (!address.isNull(4))
|
||||||
|
a.setPostalCode(address.getString(4));
|
||||||
|
if (!address.isNull(5))
|
||||||
|
a.setCountry(address.getString(5));
|
||||||
|
if (!address.isNull(6))
|
||||||
|
a.setLabel(address.getString(6));
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME:
|
||||||
|
a.setParameter("TYPE", AddressType.HOME.getValue());
|
||||||
|
break;
|
||||||
|
case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK:
|
||||||
|
a.setParameter("TYPE", AddressType.WORK.getValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vcard.addAddress(a);
|
||||||
|
}
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.w(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Cursor web = resolver.query(ContactsContract.Data.CONTENT_URI,
|
||||||
|
new String[]{
|
||||||
|
ContactsContract.CommonDataKinds.Website.TYPE,
|
||||||
|
ContactsContract.CommonDataKinds.Website.URL
|
||||||
|
},
|
||||||
|
ContactsContract.Data.CONTACT_ID + " = " + contactId +
|
||||||
|
" AND " + ContactsContract.Contacts.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE + "'",
|
||||||
|
null, null)) {
|
||||||
|
while (web.moveToNext()) {
|
||||||
|
int type = web.getInt(0);
|
||||||
|
String url = web.getString(1);
|
||||||
|
vcard.addUrl(url);
|
||||||
|
}
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.w(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Cursor phones = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
||||||
|
new String[]{
|
||||||
|
ContactsContract.CommonDataKinds.Phone.TYPE,
|
||||||
|
ContactsContract.CommonDataKinds.Phone.NUMBER
|
||||||
|
},
|
||||||
|
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId,
|
||||||
|
null, null)) {
|
||||||
|
while (phones.moveToNext()) {
|
||||||
|
int type = phones.getInt(0);
|
||||||
|
String number = phones.getString(1);
|
||||||
|
switch (type) {
|
||||||
|
case ContactsContract.CommonDataKinds.Phone.TYPE_HOME:
|
||||||
|
vcard.addTelephoneNumber(number, TelephoneType.HOME);
|
||||||
|
break;
|
||||||
|
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK:
|
||||||
|
vcard.addTelephoneNumber(number, TelephoneType.WORK);
|
||||||
|
break;
|
||||||
|
case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE:
|
||||||
|
vcard.addTelephoneNumber(number, TelephoneType.CELL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.w(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.w(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.beginTransaction();
|
||||||
|
|
||||||
|
for (EntityAttachment attachment : new ArrayList<>(attachments))
|
||||||
|
if (attachment.cid != null && attachment.cid.startsWith(EntityAttachment.VCARD_PREFIX)) {
|
||||||
|
db.attachment().deleteAttachment(attachment.id);
|
||||||
|
attachments.remove(attachment);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vcard != null) {
|
||||||
|
EntityAttachment attachment = new EntityAttachment();
|
||||||
|
attachment.message = message.id;
|
||||||
|
attachment.sequence = db.attachment().getAttachmentSequence(message.id) + 1;
|
||||||
|
attachment.name = "contact.vcf";
|
||||||
|
attachment.type = "text/vcard";
|
||||||
|
attachment.disposition = Part.ATTACHMENT;
|
||||||
|
attachment.cid = EntityAttachment.VCARD_PREFIX + Math.abs(identity.uri.hashCode());
|
||||||
|
attachment.size = null;
|
||||||
|
attachment.progress = 0;
|
||||||
|
attachment.id = db.attachment().insertAttachment(attachment);
|
||||||
|
|
||||||
|
File file = attachment.getFile(context);
|
||||||
|
try (VCardWriter writer = new VCardWriter(file, VCardVersion.V3_0)) {
|
||||||
|
writer.write(vcard);
|
||||||
|
}
|
||||||
|
|
||||||
|
attachment.size = file.length();
|
||||||
|
attachment.progress = null;
|
||||||
|
attachment.available = true;
|
||||||
|
db.attachment().setDownloaded(attachment.id, attachment.size);
|
||||||
|
|
||||||
|
attachments.add(attachment);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.w(ex);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -774,6 +774,27 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/etInternal" />
|
app:layout_constraintTop_toBottomOf="@id/etInternal" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnUri"
|
||||||
|
style="?android:attr/buttonStyleSmall"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:drawableEnd="@drawable/twotone_person_24"
|
||||||
|
android:drawablePadding="6dp"
|
||||||
|
android:text="@string/title_identity_uri"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvInternalHint" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvUri"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Contact URI"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/btnUri" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvE2Encryption"
|
android:id="@+id/tvE2Encryption"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -782,7 +803,7 @@
|
||||||
android:text="@string/title_advanced_e2e_encryption"
|
android:text="@string/title_advanced_e2e_encryption"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/tvInternalHint" />
|
app:layout_constraintTop_toBottomOf="@id/tvUri" />
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/cbSignDefault"
|
android:id="@+id/cbSignDefault"
|
||||||
|
@ -986,6 +1007,7 @@
|
||||||
cbSenderExtra,cbSenderExtraName,cbReplyExtraName,tvSenderExtra,etSenderExtra,ibSenderExtra,tvSenderExtraHint,
|
cbSenderExtra,cbSenderExtraName,cbReplyExtraName,tvSenderExtra,etSenderExtra,ibSenderExtra,tvSenderExtraHint,
|
||||||
tvReplyTo,etReplyTo,tvCc,etCc,tvCcHint,tvBcc,etBcc,tvBccHint,
|
tvReplyTo,etReplyTo,tvCc,etCc,tvCcHint,tvBcc,etBcc,tvBccHint,
|
||||||
tvInternal,etInternal,tvInternalHint,
|
tvInternal,etInternal,tvInternalHint,
|
||||||
|
btnUri,tvUri,
|
||||||
tvE2Encryption,cbSignDefault,cbEncryptDefault,
|
tvE2Encryption,cbSignDefault,cbEncryptDefault,
|
||||||
cbUnicode,tvUnicodeHint,cbOctetMime,tvMaxSize,etMaxSize" />
|
cbUnicode,tvUnicodeHint,cbOctetMime,tvMaxSize,etMaxSize" />
|
||||||
|
|
||||||
|
|
|
@ -1067,6 +1067,7 @@
|
||||||
<string name="title_advanced_sender_regex">Regex to match username of incoming email addresses</string>
|
<string name="title_advanced_sender_regex">Regex to match username of incoming email addresses</string>
|
||||||
<string name="title_identity_reply_to">Reply to address</string>
|
<string name="title_identity_reply_to">Reply to address</string>
|
||||||
<string name="title_identity_internal">Internal domain names (comma separated)</string>
|
<string name="title_identity_internal">Internal domain names (comma separated)</string>
|
||||||
|
<string name="title_identity_uri" translatable="false">Link contact</string>
|
||||||
<string name="title_identity_unicode">Allow UTF-8 in message headers</string>
|
<string name="title_identity_unicode">Allow UTF-8 in message headers</string>
|
||||||
<string name="title_identity_unicode_remark">Most servers do not support this</string>
|
<string name="title_identity_unicode_remark">Most servers do not support this</string>
|
||||||
<string name="title_identity_octetmime">Allow 8BITMIME</string>
|
<string name="title_identity_octetmime">Allow 8BITMIME</string>
|
||||||
|
|
Loading…
Reference in New Issue