mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-04 16:16:33 +02:00
Added attachments to templates
This commit is contained in:
@@ -72,7 +72,7 @@ public class AI {
|
||||
DB db = DB.getInstance(context);
|
||||
EntityAnswer t = db.answer().getAnswer(template);
|
||||
if (t != null) {
|
||||
String html = t.getHtml(context, null);
|
||||
String html = t.getData(context, null).getHtml();
|
||||
prompt = JsoupEx.parse(html).body().text();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class ActivityAnswer extends ActivityBase {
|
||||
}
|
||||
});
|
||||
|
||||
String html = answer.getHtml(context, null);
|
||||
String html = answer.getData(context, null).getHtml();
|
||||
String text = HtmlHelper.getText(context, html);
|
||||
|
||||
ClipboardManager cbm = Helper.getSystemService(ActivityAnswer.this, ClipboardManager.class);
|
||||
|
||||
@@ -396,7 +396,7 @@ public class EditTextCompose extends FixedEditText {
|
||||
|
||||
for (EntityAnswer snippet : snippets)
|
||||
if (snippet.id.equals(id)) {
|
||||
String html = snippet.getHtml(context, to);
|
||||
String html = snippet.getData(context, to).getHtml();
|
||||
|
||||
Helper.getUIExecutor().submit(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.content.SharedPreferences;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
@@ -45,6 +46,10 @@ import androidx.room.PrimaryKey;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.nodes.Node;
|
||||
import org.jsoup.nodes.TextNode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.Collator;
|
||||
@@ -63,6 +68,7 @@ import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.mail.Address;
|
||||
import javax.mail.Part;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
// https://developer.android.com/training/data-storage/room/defining-data
|
||||
@@ -107,9 +113,33 @@ public class EntityAnswer implements Serializable {
|
||||
public Integer applied = 0;
|
||||
public Long last_applied;
|
||||
|
||||
static final String ATTACHMENT_PREFIX = "[attachment:";
|
||||
static final String ATTACHMENT_SUFFIX = "]";
|
||||
private static final String PREF_PLACEHOLDER = "answer.value.";
|
||||
|
||||
String getHtml(Context context, Address[] address) {
|
||||
@NonNull
|
||||
Data getData(Context context, Address[] address) {
|
||||
Data result = new Data();
|
||||
|
||||
Document doc = JsoupEx.parse(text);
|
||||
for (Element span : doc.select("span")) {
|
||||
Node node = span.firstChild();
|
||||
if (node instanceof TextNode) {
|
||||
String text = ((TextNode) node).getWholeText().trim();
|
||||
if (text.startsWith(ATTACHMENT_PREFIX) && text.endsWith(ATTACHMENT_SUFFIX)) {
|
||||
String name = text.substring(ATTACHMENT_PREFIX.length(), text.length() - 1);
|
||||
result.attachments.add(Uri.parse(name));
|
||||
|
||||
Element next = span.nextElementSibling();
|
||||
span.remove();
|
||||
if (next != null && "br".equals(next.nodeName()))
|
||||
next.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.html = doc.html();
|
||||
|
||||
String fullName = null;
|
||||
String email = null;
|
||||
if (address != null && address.length > 0) {
|
||||
@@ -179,19 +209,19 @@ public class EntityAnswer implements Serializable {
|
||||
first = Helper.trim(first, ".");
|
||||
last = Helper.trim(last, ".");
|
||||
|
||||
text = text.replace("$name$", fullName == null ? "" : Html.escapeHtml(fullName));
|
||||
text = text.replace("$firstname$", first == null ? "" : Html.escapeHtml(first));
|
||||
text = text.replace("$lastname$", last == null ? "" : Html.escapeHtml(last));
|
||||
text = text.replace("$email$", email == null ? "" : Html.escapeHtml(email));
|
||||
result.html = result.html.replace("$name$", fullName == null ? "" : Html.escapeHtml(fullName));
|
||||
result.html = result.html.replace("$firstname$", first == null ? "" : Html.escapeHtml(first));
|
||||
result.html = result.html.replace("$lastname$", last == null ? "" : Html.escapeHtml(last));
|
||||
result.html = result.html.replace("$email$", email == null ? "" : Html.escapeHtml(email));
|
||||
|
||||
int s = text.indexOf("$date");
|
||||
int s = result.html.indexOf("$date");
|
||||
while (s >= 0) {
|
||||
int e = text.indexOf('$', s + 5);
|
||||
int e = result.html.indexOf('$', s + 5);
|
||||
if (e < 0)
|
||||
break;
|
||||
|
||||
Calendar c = null;
|
||||
String v = text.substring(s + 5, e);
|
||||
String v = result.html.substring(s + 5, e);
|
||||
if (v.startsWith("-") || v.startsWith("+")) {
|
||||
Integer days = Helper.parseInt(v.substring(1));
|
||||
if (days != null && days >= 0 && days < 10 * 365) {
|
||||
@@ -202,15 +232,15 @@ public class EntityAnswer implements Serializable {
|
||||
c = Calendar.getInstance();
|
||||
|
||||
if (c == null)
|
||||
s = text.indexOf("$date", e + 1);
|
||||
s = result.html.indexOf("$date", e + 1);
|
||||
else {
|
||||
v = Html.escapeHtml(SimpleDateFormat.getDateInstance(SimpleDateFormat.LONG).format(c.getTime()));
|
||||
text = text.substring(0, s) + v + text.substring(e + 1);
|
||||
s = text.indexOf("$date", s + v.length());
|
||||
result.html = result.html.substring(0, s) + v + result.html.substring(e + 1);
|
||||
s = result.html.indexOf("$date", s + v.length());
|
||||
}
|
||||
}
|
||||
|
||||
text = text.replace("$weekday$", new SimpleDateFormat("EEEE").format(new Date()));
|
||||
result.html = result.html.replace("$weekday$", new SimpleDateFormat("EEEE").format(new Date()));
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
for (String key : prefs.getAll().keySet())
|
||||
@@ -222,13 +252,13 @@ public class EntityAnswer implements Serializable {
|
||||
for (int i = 0; i < lines.length; i++)
|
||||
lines[i] = Html.escapeHtml(lines[i]);
|
||||
|
||||
text = text.replace("$" + name + "$", TextUtils.join("<br>", lines));
|
||||
result.html = result.html.replace("$" + name + "$", TextUtils.join("<br>", lines));
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG)
|
||||
text = text.replace("$version$", BuildConfig.VERSION_NAME);
|
||||
result.html = result.html.replace("$version$", BuildConfig.VERSION_NAME);
|
||||
|
||||
return text;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void setCustomPlaceholder(Context context, String name, String value) {
|
||||
@@ -536,4 +566,37 @@ public class EntityAnswer implements Serializable {
|
||||
public String toString() {
|
||||
return name + (favorite ? " ★" : "");
|
||||
}
|
||||
|
||||
public class Data {
|
||||
private String html;
|
||||
private List<Uri> attachments = new ArrayList<>();
|
||||
|
||||
public String getHtml() {
|
||||
return this.html;
|
||||
}
|
||||
|
||||
public void insertAttachments(Context context, long id) {
|
||||
DB db = DB.getInstance(context);
|
||||
for (Uri file : attachments)
|
||||
try {
|
||||
EntityAttachment attachment = new EntityAttachment();
|
||||
Helper.UriInfo info = Helper.getInfo(file, context);
|
||||
|
||||
attachment.message = id;
|
||||
attachment.sequence = db.attachment().getAttachmentSequence(id) + 1;
|
||||
attachment.name = info.name;
|
||||
attachment.type = info.type;
|
||||
attachment.disposition = Part.ATTACHMENT;
|
||||
attachment.size = info.size;
|
||||
attachment.progress = 0;
|
||||
|
||||
attachment.id = db.attachment().insertAttachment(attachment);
|
||||
|
||||
long size = Helper.copy(context, file, attachment.getFile(context));
|
||||
db.attachment().setDownloaded(attachment.id, size);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1159,10 +1159,12 @@ public class EntityRule {
|
||||
reply.id = db.message().insertMessage(reply);
|
||||
|
||||
String body;
|
||||
EntityAnswer.Data answerData = null;
|
||||
if (resend)
|
||||
body = Helper.readText(message.getFile(context));
|
||||
else {
|
||||
body = answer.getHtml(context, message.from);
|
||||
answerData = answer.getData(context, message.from);
|
||||
body = answerData.getHtml();
|
||||
|
||||
if (original_text) {
|
||||
Document msg = JsoupEx.parse(body);
|
||||
@@ -1219,6 +1221,9 @@ public class EntityRule {
|
||||
db.attachment().setDownloaded(attachment.id, target.length());
|
||||
}
|
||||
|
||||
if (answerData != null)
|
||||
answerData.insertAttachments(context, reply.id);
|
||||
|
||||
EntityOperation.queue(context, reply, EntityOperation.SEND);
|
||||
|
||||
// Batch send operations, wait until after commit
|
||||
|
||||
@@ -90,8 +90,9 @@ public class FragmentAnswer extends FragmentBase {
|
||||
|
||||
private static final int REQUEST_COLOR = 1;
|
||||
private static final int REQUEST_IMAGE = 2;
|
||||
private static final int REQUEST_LINK = 3;
|
||||
private final static int REQUEST_DELETE = 4;
|
||||
private static final int REQUEST_FILE = 3;
|
||||
private static final int REQUEST_LINK = 4;
|
||||
private final static int REQUEST_DELETE = 5;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -185,6 +186,9 @@ public class FragmentAnswer extends FragmentBase {
|
||||
if (itemId == R.id.action_insert_image) {
|
||||
onInsertImage();
|
||||
return true;
|
||||
} else if (itemId == R.id.action_attach_file) {
|
||||
onAttachFile();
|
||||
return true;
|
||||
} else if (itemId == R.id.action_insert_link) {
|
||||
onInsertLink();
|
||||
return true;
|
||||
@@ -413,6 +417,16 @@ public class FragmentAnswer extends FragmentBase {
|
||||
startActivityForResult(intent, REQUEST_IMAGE);
|
||||
}
|
||||
|
||||
private void onAttachFile() {
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
intent.setType("*/*");
|
||||
Helper.openAdvanced(getContext(), intent);
|
||||
startActivityForResult(intent, REQUEST_FILE);
|
||||
}
|
||||
|
||||
private void onInsertLink() {
|
||||
FragmentDialogInsertLink fragment = new FragmentDialogInsertLink();
|
||||
fragment.setArguments(FragmentDialogInsertLink.getArguments(etText));
|
||||
@@ -567,6 +581,10 @@ public class FragmentAnswer extends FragmentBase {
|
||||
if (resultCode == RESULT_OK && data != null)
|
||||
onImageSelected(data.getData());
|
||||
break;
|
||||
case REQUEST_FILE:
|
||||
if (resultCode == RESULT_OK && data != null)
|
||||
onFileSelected(data.getData());
|
||||
break;
|
||||
case REQUEST_LINK:
|
||||
if (resultCode == RESULT_OK && data != null)
|
||||
onLinkSelected(data.getBundleExtra("args"));
|
||||
@@ -605,6 +623,26 @@ public class FragmentAnswer extends FragmentBase {
|
||||
}
|
||||
}
|
||||
|
||||
private void onFileSelected(Uri uri) {
|
||||
try {
|
||||
NoStreamException.check(uri, getContext());
|
||||
|
||||
getContext().getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
if (!Helper.isPersisted(getContext(), uri, true, false))
|
||||
throw new IllegalStateException("No permission granted to access selected file " + uri);
|
||||
|
||||
Editable edit = etText.getText();
|
||||
if (edit.length() > 0 && edit.charAt(edit.length() - 1) != '\n')
|
||||
edit.append("\n");
|
||||
edit.append(EntityAnswer.ATTACHMENT_PREFIX + uri + EntityAnswer.ATTACHMENT_SUFFIX + "\n");
|
||||
etText.setSelection(edit.length());
|
||||
} catch (NoStreamException ex) {
|
||||
ex.report(getActivity());
|
||||
} catch (Throwable ex) {
|
||||
Log.unexpectedError(getParentFragmentManager(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void onLinkSelected(Bundle args) {
|
||||
String link = args.getString("link");
|
||||
boolean image = args.getBoolean("image");
|
||||
|
||||
@@ -121,7 +121,6 @@ import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.view.MenuCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.cursoradapter.widget.SimpleCursorAdapter;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
@@ -221,7 +220,6 @@ import javax.mail.internet.MimeBodyPart;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import javax.mail.internet.MimeUtility;
|
||||
import javax.mail.internet.ParseException;
|
||||
import javax.mail.util.ByteArrayDataSource;
|
||||
|
||||
import biweekly.ICalendar;
|
||||
@@ -2498,17 +2496,19 @@ public class FragmentCompose extends FragmentBase {
|
||||
long id = intent.getLongExtra("id", -1);
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("id", id);
|
||||
args.putLong("id", working);
|
||||
args.putLong("aid", id);
|
||||
args.putString("to", etTo.getText().toString());
|
||||
|
||||
new SimpleTask<EntityAnswer>() {
|
||||
@Override
|
||||
protected EntityAnswer onExecute(Context context, Bundle args) throws Throwable {
|
||||
protected EntityAnswer onExecute(Context context, Bundle args) {
|
||||
long id = args.getLong("id");
|
||||
long aid = args.getLong("aid");
|
||||
String to = args.getString("to");
|
||||
|
||||
DB db = DB.getInstance(context);
|
||||
EntityAnswer answer = db.answer().getAnswer(id);
|
||||
EntityAnswer answer = db.answer().getAnswer(aid);
|
||||
if (answer != null) {
|
||||
InternetAddress[] tos = null;
|
||||
try {
|
||||
@@ -2516,7 +2516,8 @@ public class FragmentCompose extends FragmentBase {
|
||||
} catch (AddressException ignored) {
|
||||
}
|
||||
|
||||
String html = answer.getHtml(context, tos);
|
||||
EntityAnswer.Data answerData = answer.getData(context, tos);
|
||||
String html = answerData.getHtml();
|
||||
|
||||
Document d = HtmlHelper.sanitizeCompose(context, html, true);
|
||||
Spanned spanned = HtmlHelper.fromDocument(context, d, new HtmlHelper.ImageGetterEx() {
|
||||
@@ -2531,6 +2532,8 @@ public class FragmentCompose extends FragmentBase {
|
||||
}, null);
|
||||
args.putCharSequence("spanned", spanned);
|
||||
|
||||
answerData.insertAttachments(context, id);
|
||||
|
||||
db.answer().applyAnswer(answer.id, new Date().getTime());
|
||||
}
|
||||
|
||||
@@ -3863,7 +3866,7 @@ public class FragmentCompose extends FragmentBase {
|
||||
ArrayList<Uri> images = new ArrayList<>();
|
||||
for (Uri uri : uris)
|
||||
try {
|
||||
UriInfo info = getInfo(uri, context);
|
||||
Helper.UriInfo info = Helper.getInfo(uri, context);
|
||||
if (info.isImage())
|
||||
images.add(uri);
|
||||
else
|
||||
@@ -5151,7 +5154,7 @@ public class FragmentCompose extends FragmentBase {
|
||||
NoStreamException.check(uri, context);
|
||||
|
||||
EntityAttachment attachment = new EntityAttachment();
|
||||
UriInfo info = getInfo(uri, context);
|
||||
Helper.UriInfo info = Helper.getInfo(uri, context);
|
||||
|
||||
EntityLog.log(context, "Add attachment" +
|
||||
" uri=" + uri + " type=" + type + " image=" + image + " resize=" + resize + " privacy=" + privacy +
|
||||
@@ -5669,6 +5672,7 @@ public class FragmentCompose extends FragmentBase {
|
||||
|
||||
Document document = Document.createShell("");
|
||||
|
||||
EntityAnswer.Data answerData = null;
|
||||
if (ref == null) {
|
||||
data.draft.thread = data.draft.msgid;
|
||||
|
||||
@@ -5710,7 +5714,8 @@ public class FragmentCompose extends FragmentBase {
|
||||
if (answer > 0)
|
||||
data.draft.subject = a.name;
|
||||
if (TextUtils.isEmpty(external_body)) {
|
||||
Document d = JsoupEx.parse(a.getHtml(context, null));
|
||||
answerData = a.getData(context, null);
|
||||
Document d = JsoupEx.parse(answerData.getHtml());
|
||||
document.body().append(d.body().html());
|
||||
}
|
||||
}
|
||||
@@ -5930,7 +5935,7 @@ public class FragmentCompose extends FragmentBase {
|
||||
else {
|
||||
db.answer().applyAnswer(receipt.id, new Date().getTime());
|
||||
texts = new String[0];
|
||||
Document d = JsoupEx.parse(receipt.getHtml(context, null));
|
||||
Document d = JsoupEx.parse(receipt.getData(context, null).getHtml());
|
||||
document.body().append(d.body().html());
|
||||
}
|
||||
}
|
||||
@@ -5988,7 +5993,8 @@ public class FragmentCompose extends FragmentBase {
|
||||
db.answer().applyAnswer(a.id, new Date().getTime());
|
||||
if (a.label != null && ref != null)
|
||||
EntityOperation.queue(context, ref, EntityOperation.LABEL, a.label, true);
|
||||
Document d = JsoupEx.parse(a.getHtml(context, data.draft.to));
|
||||
answerData = a.getData(context, data.draft.to);
|
||||
Document d = JsoupEx.parse(answerData.getHtml());
|
||||
document.body().append(d.body().html());
|
||||
}
|
||||
|
||||
@@ -6196,7 +6202,7 @@ public class FragmentCompose extends FragmentBase {
|
||||
ArrayList<Uri> images = new ArrayList<>();
|
||||
for (Uri uri : uris)
|
||||
try {
|
||||
UriInfo info = getInfo(uri, context);
|
||||
Helper.UriInfo info = Helper.getInfo(uri, context);
|
||||
if (info.isImage())
|
||||
images.add(uri);
|
||||
else
|
||||
@@ -6255,6 +6261,9 @@ public class FragmentCompose extends FragmentBase {
|
||||
}
|
||||
}
|
||||
|
||||
if (answerData != null)
|
||||
answerData.insertAttachments(context, data.draft.id);
|
||||
|
||||
if (save_drafts &&
|
||||
(data.draft.ui_encrypt == null ||
|
||||
EntityMessage.ENCRYPT_NONE.equals(data.draft.ui_encrypt)) &&
|
||||
@@ -8313,67 +8322,6 @@ public class FragmentCompose extends FragmentBase {
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
private static UriInfo getInfo(Uri uri, Context context) {
|
||||
UriInfo result = new UriInfo();
|
||||
|
||||
// https://stackoverflow.com/questions/76094229/android-13-photo-video-picker-file-name-from-the-uri-is-garbage
|
||||
DocumentFile dfile = null;
|
||||
try {
|
||||
dfile = DocumentFile.fromSingleUri(context, uri);
|
||||
if (dfile != null) {
|
||||
result.name = dfile.getName();
|
||||
result.type = dfile.getType();
|
||||
result.size = dfile.length();
|
||||
EntityLog.log(context, "UriInfo dfile " + result + " uri=" + uri);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
|
||||
// Check name
|
||||
if (TextUtils.isEmpty(result.name))
|
||||
result.name = uri.getLastPathSegment();
|
||||
|
||||
// Check type
|
||||
if (!TextUtils.isEmpty(result.type))
|
||||
try {
|
||||
new ContentType(result.type);
|
||||
} catch (ParseException ex) {
|
||||
Log.w(new Throwable(result.type, ex));
|
||||
result.type = null;
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(result.type) ||
|
||||
"*/*".equals(result.type) ||
|
||||
"application/*".equals(result.type) ||
|
||||
"application/octet-stream".equals(result.type))
|
||||
result.type = Helper.guessMimeType(result.name);
|
||||
|
||||
if (result.size != null && result.size <= 0)
|
||||
result.size = null;
|
||||
|
||||
EntityLog.log(context, "UriInfo result " + result + " uri=" + uri);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class UriInfo {
|
||||
String name;
|
||||
String type;
|
||||
Long size;
|
||||
|
||||
boolean isImage() {
|
||||
return ImageHelper.isImage(type);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "name=" + name + " type=" + type + " size=" + size;
|
||||
}
|
||||
}
|
||||
|
||||
private static class DraftData {
|
||||
private EntityMessage draft;
|
||||
private List<TupleIdentityEx> identities;
|
||||
|
||||
@@ -120,6 +120,7 @@ import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.view.SoftwareKeyboardControllerCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
@@ -183,6 +184,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.mail.internet.ContentType;
|
||||
import javax.mail.internet.ParseException;
|
||||
|
||||
public class Helper {
|
||||
private static Integer targetSdk = null;
|
||||
private static Boolean hasWebView = null;
|
||||
@@ -2793,6 +2797,67 @@ public class Helper {
|
||||
return extension;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static UriInfo getInfo(Uri uri, Context context) {
|
||||
UriInfo result = new UriInfo();
|
||||
|
||||
// https://stackoverflow.com/questions/76094229/android-13-photo-video-picker-file-name-from-the-uri-is-garbage
|
||||
DocumentFile dfile = null;
|
||||
try {
|
||||
dfile = DocumentFile.fromSingleUri(context, uri);
|
||||
if (dfile != null) {
|
||||
result.name = dfile.getName();
|
||||
result.type = dfile.getType();
|
||||
result.size = dfile.length();
|
||||
EntityLog.log(context, "UriInfo dfile " + result + " uri=" + uri);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
|
||||
// Check name
|
||||
if (TextUtils.isEmpty(result.name))
|
||||
result.name = uri.getLastPathSegment();
|
||||
|
||||
// Check type
|
||||
if (!TextUtils.isEmpty(result.type))
|
||||
try {
|
||||
new ContentType(result.type);
|
||||
} catch (ParseException ex) {
|
||||
Log.w(new Throwable(result.type, ex));
|
||||
result.type = null;
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(result.type) ||
|
||||
"*/*".equals(result.type) ||
|
||||
"application/*".equals(result.type) ||
|
||||
"application/octet-stream".equals(result.type))
|
||||
result.type = Helper.guessMimeType(result.name);
|
||||
|
||||
if (result.size != null && result.size <= 0)
|
||||
result.size = null;
|
||||
|
||||
EntityLog.log(context, "UriInfo result " + result + " uri=" + uri);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static class UriInfo {
|
||||
String name;
|
||||
String type;
|
||||
Long size;
|
||||
|
||||
boolean isImage() {
|
||||
return ImageHelper.isImage(type);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "name=" + name + " type=" + type + " size=" + size;
|
||||
}
|
||||
}
|
||||
|
||||
static void writeText(File file, String content) throws IOException {
|
||||
try (FileOutputStream out = new FileOutputStream(file)) {
|
||||
if (content != null)
|
||||
|
||||
@@ -326,7 +326,8 @@ public class ServiceExternal extends ServiceBase {
|
||||
new InternetAddress(identity.get(0).email, identity.get(0).name, StandardCharsets.UTF_8.name())};
|
||||
if (subject == null) // Allow empty string
|
||||
subject = answers.get(0).name;
|
||||
String body = answers.get(0).getHtml(context, to);
|
||||
EntityAnswer.Data answerData = answers.get(0).getData(context, to);
|
||||
String body = answerData.getHtml();
|
||||
|
||||
EntityMessage msg = new EntityMessage();
|
||||
msg.account = identity.get(0).account;
|
||||
@@ -356,6 +357,8 @@ public class ServiceExternal extends ServiceBase {
|
||||
msg.preview,
|
||||
null);
|
||||
|
||||
answerData.insertAttachments(context, msg.id);
|
||||
|
||||
EntityOperation.queue(context, msg, EntityOperation.SEND);
|
||||
ServiceSend.start(context);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user