mirror of https://github.com/M66B/FairEmail.git
Load inline images async, named tasks
This commit is contained in:
parent
b9dd42772a
commit
4c53f9b5b1
|
@ -97,10 +97,6 @@ public abstract class DB extends RoomDatabase {
|
||||||
return sInstance;
|
return sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized DB getInstanceMainThread(Context context) {
|
|
||||||
return migrate(context, getBuilder(context).allowMainThreadQueries());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RoomDatabase.Builder getBuilder(Context context) {
|
private static RoomDatabase.Builder getBuilder(Context context) {
|
||||||
return Room
|
return Room
|
||||||
.databaseBuilder(context.getApplicationContext(), DB.class, DB_NAME)
|
.databaseBuilder(context.getApplicationContext(), DB.class, DB_NAME)
|
||||||
|
|
|
@ -30,9 +30,11 @@ import android.content.Intent;
|
||||||
import android.content.IntentSender;
|
import android.content.IntentSender;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.LevelListDrawable;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
|
@ -40,6 +42,7 @@ import android.net.NetworkRequest;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.provider.OpenableColumns;
|
import android.provider.OpenableColumns;
|
||||||
|
@ -493,7 +496,7 @@ public class FragmentCompose extends FragmentEx {
|
||||||
args.putString("subject", getArguments().getString("subject"));
|
args.putString("subject", getArguments().getString("subject"));
|
||||||
args.putString("body", getArguments().getString("body"));
|
args.putString("body", getArguments().getString("body"));
|
||||||
args.putParcelableArrayList("attachments", getArguments().getParcelableArrayList("attachments"));
|
args.putParcelableArrayList("attachments", getArguments().getParcelableArrayList("attachments"));
|
||||||
draftLoader.execute(this, args);
|
draftLoader.execute(this, args, "draft:new");
|
||||||
} else {
|
} else {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString("action", "edit");
|
args.putString("action", "edit");
|
||||||
|
@ -501,7 +504,7 @@ public class FragmentCompose extends FragmentEx {
|
||||||
args.putLong("account", -1);
|
args.putLong("account", -1);
|
||||||
args.putLong("reference", -1);
|
args.putLong("reference", -1);
|
||||||
args.putLong("answer", -1);
|
args.putLong("answer", -1);
|
||||||
draftLoader.execute(this, args);
|
draftLoader.execute(this, args, "draft:edit");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
working = savedInstanceState.getLong("working");
|
working = savedInstanceState.getLong("working");
|
||||||
|
@ -511,7 +514,7 @@ public class FragmentCompose extends FragmentEx {
|
||||||
args.putLong("account", -1);
|
args.putLong("account", -1);
|
||||||
args.putLong("reference", -1);
|
args.putLong("reference", -1);
|
||||||
args.putLong("answer", -1);
|
args.putLong("answer", -1);
|
||||||
draftLoader.execute(this, args);
|
draftLoader.execute(this, args, "draft:instance");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,7 +915,7 @@ public class FragmentCompose extends FragmentEx {
|
||||||
else
|
else
|
||||||
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
||||||
}
|
}
|
||||||
}.execute(this, args);
|
}.execute(this, args, "encrypt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1040,7 +1043,7 @@ public class FragmentCompose extends FragmentEx {
|
||||||
else
|
else
|
||||||
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
||||||
}
|
}
|
||||||
}.execute(this, args);
|
}.execute(this, args, "add:attachment");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleExit() {
|
private void handleExit() {
|
||||||
|
@ -1098,7 +1101,7 @@ public class FragmentCompose extends FragmentEx {
|
||||||
dirty = false;
|
dirty = false;
|
||||||
|
|
||||||
Log.i("Run execute id=" + working);
|
Log.i("Run execute id=" + working);
|
||||||
actionLoader.execute(this, args);
|
actionLoader.execute(this, args, "action:" + action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isEmpty() {
|
private boolean isEmpty() {
|
||||||
|
@ -1655,7 +1658,7 @@ public class FragmentCompose extends FragmentEx {
|
||||||
protected void onException(Bundle args, Throwable ex) {
|
protected void onException(Bundle args, Throwable ex) {
|
||||||
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
||||||
}
|
}
|
||||||
}.execute(this, args);
|
}.execute(this, args, "draft:check");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showDraft(EntityMessage draft) {
|
private void showDraft(EntityMessage draft) {
|
||||||
|
@ -1667,11 +1670,6 @@ public class FragmentCompose extends FragmentEx {
|
||||||
args.putLong("reference", draft.forwarding);
|
args.putLong("reference", draft.forwarding);
|
||||||
|
|
||||||
new SimpleTask<Spanned[]>() {
|
new SimpleTask<Spanned[]>() {
|
||||||
@Override
|
|
||||||
protected void onPreExecute(Bundle args) {
|
|
||||||
state = State.LOADING;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Bundle args) {
|
protected void onPostExecute(Bundle args) {
|
||||||
state = State.LOADED;
|
state = State.LOADED;
|
||||||
|
@ -1731,7 +1729,7 @@ public class FragmentCompose extends FragmentEx {
|
||||||
protected void onException(Bundle args, Throwable ex) {
|
protected void onException(Bundle args, Throwable ex) {
|
||||||
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
||||||
}
|
}
|
||||||
}.execute(FragmentCompose.this, args);
|
}.execute(FragmentCompose.this, args, "draft:show");
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimpleTask<EntityMessage> actionLoader = new SimpleTask<EntityMessage>() {
|
private SimpleTask<EntityMessage> actionLoader = new SimpleTask<EntityMessage>() {
|
||||||
|
@ -1989,25 +1987,72 @@ public class FragmentCompose extends FragmentEx {
|
||||||
|
|
||||||
private Html.ImageGetter cidGetter = new Html.ImageGetter() {
|
private Html.ImageGetter cidGetter = new Html.ImageGetter() {
|
||||||
@Override
|
@Override
|
||||||
public Drawable getDrawable(String source) {
|
public Drawable getDrawable(final String source) {
|
||||||
if (source != null && source.startsWith("cid:")) {
|
final LevelListDrawable lld = new LevelListDrawable();
|
||||||
DB db = DB.getInstanceMainThread(getContext());
|
|
||||||
String cid = "<" + source.substring(4) + ">";
|
|
||||||
EntityAttachment attachment = db.attachment().getAttachment(working, cid);
|
|
||||||
if (attachment != null) {
|
|
||||||
File file = EntityAttachment.getFile(getContext(), attachment.id);
|
|
||||||
Drawable d = Drawable.createFromPath(file.getAbsolutePath());
|
|
||||||
if (d != null) {
|
|
||||||
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Resources res = getContext().getResources();
|
||||||
int px = Helper.dp2pixels(getContext(), 48);
|
int px = Helper.dp2pixels(getContext(), 48);
|
||||||
Drawable d = getContext().getResources().getDrawable(R.drawable.baseline_broken_image_24, getContext().getTheme());
|
|
||||||
d.setBounds(0, 0, px, px);
|
// Level 0: broken image
|
||||||
return d;
|
Drawable broken = res.getDrawable(R.drawable.baseline_broken_image_24, getContext().getTheme());
|
||||||
|
broken.setBounds(0, 0, px, px);
|
||||||
|
lld.addLevel(0, 0, broken);
|
||||||
|
|
||||||
|
// Level 1: place holder
|
||||||
|
Drawable placeholder = res.getDrawable(R.drawable.baseline_image_24, getContext().getTheme());
|
||||||
|
placeholder.setBounds(0, 0, px, px);
|
||||||
|
lld.addLevel(1, 1, placeholder);
|
||||||
|
|
||||||
|
lld.setBounds(0, 0, px, px);
|
||||||
|
|
||||||
|
if (source != null && source.startsWith("cid:")) {
|
||||||
|
lld.setLevel(1); // placeholder
|
||||||
|
|
||||||
|
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putLong("id", working);
|
||||||
|
args.putString("cid", "<" + source.substring(4) + ">");
|
||||||
|
|
||||||
|
new SimpleTask<Drawable>() {
|
||||||
|
@Override
|
||||||
|
protected Drawable onExecute(Context context, Bundle args) {
|
||||||
|
long id = args.getLong("id");
|
||||||
|
String cid = args.getString("cid");
|
||||||
|
|
||||||
|
DB db = DB.getInstance(context);
|
||||||
|
EntityAttachment attachment = db.attachment().getAttachment(id, cid);
|
||||||
|
if (attachment == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
File file = EntityAttachment.getFile(getContext(), attachment.id);
|
||||||
|
return Drawable.createFromPath(file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onExecuted(Bundle args, Drawable image) {
|
||||||
|
if (image == null)
|
||||||
|
lld.setLevel(0); // broken
|
||||||
|
else {
|
||||||
|
lld.addLevel(2, 2, image);
|
||||||
|
lld.setLevel(2); // image
|
||||||
|
lld.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
|
||||||
|
}
|
||||||
|
etBody.requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onException(Bundle args, Throwable ex) {
|
||||||
|
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
||||||
|
}
|
||||||
|
}.execute(FragmentCompose.this, args, source);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
lld.setLevel(0); // broken
|
||||||
|
|
||||||
|
return lld;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import android.os.Handler;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.Lifecycle;
|
import androidx.lifecycle.Lifecycle;
|
||||||
|
@ -45,25 +46,30 @@ public abstract class SimpleTask<T> implements LifecycleObserver {
|
||||||
private boolean paused;
|
private boolean paused;
|
||||||
private boolean destroyed;
|
private boolean destroyed;
|
||||||
private Bundle args;
|
private Bundle args;
|
||||||
|
private String name;
|
||||||
private Result stored;
|
private Result stored;
|
||||||
|
|
||||||
private static ExecutorService executor = Executors.newCachedThreadPool(Helper.backgroundThreadFactory);
|
private static ExecutorService executor = Executors.newCachedThreadPool(Helper.backgroundThreadFactory);
|
||||||
|
|
||||||
public void execute(Context context, LifecycleOwner owner, Bundle args) {
|
public void execute(Context context, LifecycleOwner owner, Bundle args) {
|
||||||
run(context, owner, args);
|
run(context, owner, args, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(LifecycleService service, Bundle args) {
|
public void execute(LifecycleService service, Bundle args) {
|
||||||
run(service, service, args);
|
run(service, service, args, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(AppCompatActivity activity, Bundle args) {
|
public void execute(AppCompatActivity activity, Bundle args) {
|
||||||
run(activity, activity, args);
|
run(activity, activity, args, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(final Fragment fragment, Bundle args) {
|
public void execute(Fragment fragment, Bundle args) {
|
||||||
|
execute(fragment, args, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execute(final Fragment fragment, Bundle args, String name) {
|
||||||
try {
|
try {
|
||||||
run(fragment.getContext(), fragment.getViewLifecycleOwner(), args);
|
run(fragment.getContext(), fragment.getViewLifecycleOwner(), args, name);
|
||||||
} catch (IllegalStateException ex) {
|
} catch (IllegalStateException ex) {
|
||||||
Log.w(ex);
|
Log.w(ex);
|
||||||
}
|
}
|
||||||
|
@ -111,11 +117,12 @@ public abstract class SimpleTask<T> implements LifecycleObserver {
|
||||||
stored = null;
|
stored = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run(final Context context, LifecycleOwner owner, final Bundle args) {
|
private void run(final Context context, LifecycleOwner owner, final Bundle args, String name) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.paused = false;
|
this.paused = false;
|
||||||
this.destroyed = false;
|
this.destroyed = false;
|
||||||
this.args = null;
|
this.args = null;
|
||||||
|
this.name = name;
|
||||||
this.stored = null;
|
this.stored = null;
|
||||||
|
|
||||||
owner.getLifecycle().addObserver(this);
|
owner.getLifecycle().addObserver(this);
|
||||||
|
@ -198,4 +205,10 @@ public abstract class SimpleTask<T> implements LifecycleObserver {
|
||||||
Throwable ex;
|
Throwable ex;
|
||||||
Object data;
|
Object data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return (name == null ? super.toString() : name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue