mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-06 00:53:26 +02:00
Store message preview
This commit is contained in:
@@ -66,7 +66,6 @@ import android.widget.Toast;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
import java.io.File;
|
||||
@@ -333,38 +332,8 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
|
||||
ivAttachments.setVisibility(message.attachments > 0 ? View.VISIBLE : View.GONE);
|
||||
tvSubject.setText(message.subject);
|
||||
|
||||
tvPreview.setVisibility(View.GONE);
|
||||
if (preview && message.content) {
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable("message", message);
|
||||
|
||||
new SimpleTask<String>() {
|
||||
@Override
|
||||
protected void onInit(Bundle args) {
|
||||
tvPreview.setHasTransientState(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String onLoad(Context context, Bundle args) throws Throwable {
|
||||
TupleMessageEx message = (TupleMessageEx) args.getSerializable("message");
|
||||
String body = message.read(context);
|
||||
return Jsoup.parse(body).text();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoaded(Bundle args, String preview) {
|
||||
tvPreview.setText(preview);
|
||||
tvPreview.setVisibility(View.VISIBLE);
|
||||
tvPreview.setHasTransientState(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
tvPreview.setHasTransientState(false);
|
||||
Helper.unexpectedError(context, ex);
|
||||
}
|
||||
}.load(context, owner, args);
|
||||
}
|
||||
tvPreview.setText(message.preview);
|
||||
tvPreview.setVisibility(preview && !TextUtils.isEmpty(message.preview) ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (viewType == ViewType.UNIFIED)
|
||||
tvFolder.setText(message.accountName);
|
||||
|
||||
@@ -45,7 +45,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||
|
||||
@Database(
|
||||
version = 23,
|
||||
version = 24,
|
||||
entities = {
|
||||
EntityIdentity.class,
|
||||
EntityAccount.class,
|
||||
@@ -284,6 +284,13 @@ public abstract class DB extends RoomDatabase {
|
||||
db.execSQL("ALTER TABLE `identity` ADD COLUMN `insecure` INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
})
|
||||
.addMigrations(new Migration(23, 24) {
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase db) {
|
||||
Log.i(Helper.TAG, "DB migration from version " + startVersion + " to " + endVersion);
|
||||
db.execSQL("ALTER TABLE `message` ADD COLUMN `preview` TEXT");
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,11 @@ public interface DaoMessage {
|
||||
" AND ui_seen")
|
||||
List<EntityMessage> getMessageSeen(long folder);
|
||||
|
||||
@Query("SELECT id FROM message" +
|
||||
" WHERE content" +
|
||||
" AND preview IS NULL")
|
||||
List<Long> getMessageWithoutPreview();
|
||||
|
||||
@Query("SELECT message.*" +
|
||||
", account.name AS accountName, account.color AS accountColor" +
|
||||
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" +
|
||||
@@ -220,8 +225,8 @@ public interface DaoMessage {
|
||||
@Query("UPDATE message SET error = :error WHERE id = :id")
|
||||
int setMessageError(long id, String error);
|
||||
|
||||
@Query("UPDATE message SET content = :content WHERE id = :id")
|
||||
int setMessageContent(long id, boolean content);
|
||||
@Query("UPDATE message SET content = NOT preview IS NULL, preview = :preview WHERE id = :id")
|
||||
int setMessageContent(long id, String preview);
|
||||
|
||||
@Query("UPDATE message SET headers = :headers WHERE id = :id")
|
||||
int setMessageHeaders(long id, String headers);
|
||||
|
||||
@@ -94,6 +94,7 @@ public class EntityMessage implements Serializable {
|
||||
public Integer size;
|
||||
@NonNull
|
||||
public Boolean content = false;
|
||||
public String preview;
|
||||
public Long sent; // compose = null
|
||||
@NonNull
|
||||
public Long received; // compose = stored
|
||||
@@ -198,6 +199,7 @@ public class EntityMessage implements Serializable {
|
||||
(this.subject == null ? other.subject == null : this.subject.equals(other.subject)) &&
|
||||
(this.size == null ? other.size == null : this.size.equals(other.size)) &&
|
||||
this.content == other.content &&
|
||||
(this.preview == null ? other.preview == null : this.preview.equals(other.preview)) &&
|
||||
(this.sent == null ? other.sent == null : this.sent.equals(other.sent)) &&
|
||||
this.received.equals(other.received) &&
|
||||
this.stored.equals(other.stored) &&
|
||||
|
||||
@@ -19,9 +19,12 @@ package eu.faircode.email;
|
||||
Copyright 2018 by Marcel Bokhorst (M66B)
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -29,6 +32,10 @@ import android.widget.AdapterView;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
@@ -113,6 +120,36 @@ public class FragmentOptions extends FragmentEx {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
|
||||
prefs.edit().putBoolean("preview", checked).apply();
|
||||
if (checked)
|
||||
new SimpleTask<Void>() {
|
||||
@Override
|
||||
protected Void onLoad(Context context, Bundle args) {
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
|
||||
boolean metered = (cm == null || cm.isActiveNetworkMetered());
|
||||
|
||||
for (Long id : db.message().getMessageWithoutPreview()) {
|
||||
EntityMessage message = db.message().getMessage(id);
|
||||
try {
|
||||
Log.i(Helper.TAG, "Building preview id=" + id);
|
||||
String html = message.read(context);
|
||||
String text = Jsoup.parse(html).text();
|
||||
String preview = text.substring(0, Math.min(text.length(), 250));
|
||||
db.message().setMessageContent(message.id, preview);
|
||||
} catch (IOException ex) {
|
||||
Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex));
|
||||
db.message().setMessageContent(message.id, null);
|
||||
if (!metered)
|
||||
EntityOperation.queue(db, message, EntityOperation.BODY);
|
||||
}
|
||||
}
|
||||
|
||||
EntityOperation.process(context);
|
||||
|
||||
return null;
|
||||
}
|
||||
}.load(FragmentOptions.this, null);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ import com.sun.mail.util.MailConnectException;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.jsoup.Jsoup;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
@@ -134,6 +135,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
private static final int SYNC_BATCH_SIZE = 20;
|
||||
private static final int DOWNLOAD_BATCH_SIZE = 20;
|
||||
private static final long RECONNECT_BACKOFF = 90 * 1000L; // milliseconds
|
||||
private static final int PREVIEW_SIZE = 250;
|
||||
|
||||
static final int PI_CLEAR = 1;
|
||||
static final int PI_SEEN = 2;
|
||||
@@ -1432,8 +1434,11 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
throw new MessageRemovedException();
|
||||
|
||||
MessageHelper helper = new MessageHelper((MimeMessage) imessage);
|
||||
message.write(this, helper.getHtml());
|
||||
db.message().setMessageContent(message.id, true);
|
||||
String html = helper.getHtml();
|
||||
String text = Jsoup.parse(html).text();
|
||||
String preview = text.substring(0, Math.min(text.length(), PREVIEW_SIZE));
|
||||
message.write(this, html);
|
||||
db.message().setMessageContent(message.id, preview);
|
||||
}
|
||||
|
||||
private void doAttachment(EntityFolder folder, EntityOperation op, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws JSONException, MessagingException, IOException {
|
||||
@@ -1890,8 +1895,11 @@ public class ServiceSynchronize extends LifecycleService {
|
||||
|
||||
if (!message.content)
|
||||
if (!metered || (message.size != null && message.size < download)) {
|
||||
message.write(context, helper.getHtml());
|
||||
db.message().setMessageContent(message.id, true);
|
||||
String html = helper.getHtml();
|
||||
String text = Jsoup.parse(html).text();
|
||||
String preview = text.substring(0, Math.min(text.length(), PREVIEW_SIZE));
|
||||
message.write(context, html);
|
||||
db.message().setMessageContent(message.id, preview);
|
||||
Log.i(Helper.TAG, folder.name + " downloaded message id=" + message.id + " size=" + message.size);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user