Added support for deleted flag

pull/194/head
M66B 4 years ago
parent 50686ce0c0
commit 54d806d3ed

File diff suppressed because it is too large Load Diff

@ -944,7 +944,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
view.setAlpha( view.setAlpha(
(EntityFolder.OUTBOX.equals(message.folderType) (EntityFolder.OUTBOX.equals(message.folderType)
? message.identitySynchronize == null || !message.identitySynchronize ? message.identitySynchronize == null || !message.identitySynchronize
: message.uid == null && message.accountProtocol == EntityAccount.TYPE_IMAP) : message.accountProtocol == EntityAccount.TYPE_IMAP && (message.uid == null || message.ui_deleted))
? Helper.LOW_LIGHT : 1.0f); ? Helper.LOW_LIGHT : 1.0f);
// Duplicate // Duplicate
@ -5521,6 +5521,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
// seen // seen
// answered // answered
// flagged // flagged
// deleted
if (debug && !Objects.equals(prev.flags, next.flags)) { if (debug && !Objects.equals(prev.flags, next.flags)) {
same = false; same = false;
log("flags changed", next.id); log("flags changed", next.id);
@ -5547,6 +5548,10 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
same = false; same = false;
log("ui_flagged changed", next.id); log("ui_flagged changed", next.id);
} }
if (!prev.ui_deleted.equals(next.ui_deleted)) {
same = false;
log("ui_deleted changed", next.id);
}
if (!prev.ui_hide.equals(next.ui_hide)) { if (!prev.ui_hide.equals(next.ui_hide)) {
same = false; same = false;
log("ui_hide changed", next.id); log("ui_hide changed", next.id);

@ -1252,8 +1252,6 @@ class Core {
throw new MessageRemovedException(folder.name + " fetch not found uid=" + uid); throw new MessageRemovedException(folder.name + " fetch not found uid=" + uid);
if (imessage.isExpunged()) if (imessage.isExpunged())
throw new MessageRemovedException(folder.name + " fetch expunged uid=" + uid); throw new MessageRemovedException(folder.name + " fetch expunged uid=" + uid);
if (imessage.isSet(Flags.Flag.DELETED))
throw new MessageRemovedException(folder.name + " fetch deleted uid=" + uid);
SyncStats stats = new SyncStats(); SyncStats stats = new SyncStats();
boolean download = db.folder().getFolderDownload(folder.id); boolean download = db.folder().getFolderDownload(folder.id);
@ -1322,6 +1320,8 @@ class Core {
private static void onDelete(Context context, JSONArray jargs, EntityFolder folder, EntityMessage message, IMAPFolder ifolder) throws MessagingException { private static void onDelete(Context context, JSONArray jargs, EntityFolder folder, EntityMessage message, IMAPFolder ifolder) throws MessagingException {
// Delete message // Delete message
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean perform_expunge = prefs.getBoolean("perform_expunge", true);
if (folder.local) { if (folder.local) {
Log.i(folder.name + " local delete"); Log.i(folder.name + " local delete");
@ -1366,14 +1366,11 @@ class Core {
Log.w(ex); Log.w(ex);
} }
if (deleted) { if (perform_expunge) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); if (deleted)
boolean perform_expunge = prefs.getBoolean("perform_expunge", true);
if (perform_expunge)
ifolder.expunge(); // NO EXPUNGE failed. ifolder.expunge(); // NO EXPUNGE failed.
db.message().deleteMessage(message.id);
} }
db.message().deleteMessage(message.id);
} finally { } finally {
int count = MessageHelper.getMessageCount(ifolder); int count = MessageHelper.getMessageCount(ifolder);
db.folder().setFolderTotal(folder.id, count < 0 ? null : count); db.folder().setFolderTotal(folder.id, count < 0 ? null : count);
@ -2445,9 +2442,12 @@ class Core {
int expunge = 0; int expunge = 0;
for (int i = 0; i < imessages.length && state.isRunning() && state.isRecoverable(); i++) for (int i = 0; i < imessages.length && state.isRunning() && state.isRecoverable(); i++)
try { try {
if (imessages[i].isSet(Flags.Flag.DELETED)) if (imessages[i].isSet(Flags.Flag.DELETED)) {
expunge++; if (perform_expunge)
else expunge++;
else
uids.remove(ifolder.getUID(imessages[i]));
} else
uids.remove(ifolder.getUID(imessages[i])); uids.remove(ifolder.getUID(imessages[i]));
} catch (MessageRemovedException ex) { } catch (MessageRemovedException ex) {
Log.w(folder.name, ex); Log.w(folder.name, ex);
@ -2457,7 +2457,7 @@ class Core {
db.folder().setFolderError(folder.id, Log.formatThrowable(ex)); db.folder().setFolderError(folder.id, Log.formatThrowable(ex));
} }
if (expunge > 0 && perform_expunge) if (expunge > 0)
try { try {
Log.i(folder.name + " expunging=" + expunge); Log.i(folder.name + " expunging=" + expunge);
ifolder.expunge(); ifolder.expunge();
@ -2754,6 +2754,11 @@ class Core {
IMAPStore istore, IMAPFolder ifolder, MimeMessage imessage, IMAPStore istore, IMAPFolder ifolder, MimeMessage imessage,
boolean browsed, boolean download, boolean browsed, boolean download,
List<EntityRule> rules, State state, SyncStats stats) throws MessagingException, IOException { List<EntityRule> rules, State state, SyncStats stats) throws MessagingException, IOException {
DB db = DB.getInstance(context);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean notify_known = prefs.getBoolean("notify_known", false);
boolean perform_expunge = prefs.getBoolean("perform_expunge", true);
boolean pro = ActivityBilling.isPro(context);
long uid = ifolder.getUID(imessage); long uid = ifolder.getUID(imessage);
if (uid < 0) { if (uid < 0) {
@ -2765,15 +2770,21 @@ class Core {
Log.i(folder.name + " expunged uid=" + uid); Log.i(folder.name + " expunged uid=" + uid);
throw new MessageRemovedException("Expunged"); throw new MessageRemovedException("Expunged");
} }
if (imessage.isSet(Flags.Flag.DELETED)) { if (perform_expunge && imessage.isSet(Flags.Flag.DELETED)) {
Log.i(folder.name + " deleted uid=" + uid); Log.i(folder.name + " deleted uid=" + uid);
throw new MessageRemovedException("Flagged deleted"); try {
ifolder.expunge();
} catch (MessagingException ex) {
Log.w(ex);
}
throw new MessageRemovedException("Deleted");
} }
MessageHelper helper = new MessageHelper(imessage, context); MessageHelper helper = new MessageHelper(imessage, context);
boolean seen = helper.getSeen(); boolean seen = helper.getSeen();
boolean answered = helper.getAnswered(); boolean answered = helper.getAnswered();
boolean flagged = helper.getFlagged(); boolean flagged = helper.getFlagged();
boolean deleted = helper.getDeleted();
String flags = helper.getFlags(); String flags = helper.getFlags();
String[] keywords = helper.getKeywords(); String[] keywords = helper.getKeywords();
String[] labels = helper.getLabels(); String[] labels = helper.getLabels();
@ -2781,11 +2792,6 @@ class Core {
boolean process = false; boolean process = false;
boolean syncSimilar = false; boolean syncSimilar = false;
DB db = DB.getInstance(context);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean notify_known = prefs.getBoolean("notify_known", false);
boolean pro = ActivityBilling.isPro(context);
// Find message by uid (fast, no headers required) // Find message by uid (fast, no headers required)
EntityMessage message = db.message().getMessageByUid(folder.id, uid); EntityMessage message = db.message().getMessageByUid(folder.id, uid);
@ -2907,12 +2913,14 @@ class Core {
message.seen = seen; message.seen = seen;
message.answered = answered; message.answered = answered;
message.flagged = flagged; message.flagged = flagged;
message.deleted = deleted;
message.flags = flags; message.flags = flags;
message.keywords = keywords; message.keywords = keywords;
message.labels = labels; message.labels = labels;
message.ui_seen = seen; message.ui_seen = seen;
message.ui_answered = answered; message.ui_answered = answered;
message.ui_flagged = flagged; message.ui_flagged = flagged;
message.ui_deleted = deleted;
message.ui_hide = false; message.ui_hide = false;
message.ui_found = false; message.ui_found = false;
message.ui_ignored = seen; message.ui_ignored = seen;
@ -3139,6 +3147,15 @@ class Core {
syncSimilar = true; syncSimilar = true;
} }
if ((!message.deleted.equals(deleted) || !message.ui_deleted.equals(deleted)) &&
db.operation().getOperationCount(folder.id, message.id, EntityOperation.DELETE) == 0) {
update = true;
message.deleted = deleted;
message.ui_deleted = deleted;
Log.i(folder.name + " updated id=" + message.id + " uid=" + message.uid + " deleted=" + deleted);
syncSimilar = true;
}
if (!Objects.equals(flags, message.flags)) { if (!Objects.equals(flags, message.flags)) {
update = true; update = true;
message.flags = flags; message.flags = flags;

@ -64,7 +64,7 @@ import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_PASSWORD;
// https://developer.android.com/topic/libraries/architecture/room.html // https://developer.android.com/topic/libraries/architecture/room.html
@Database( @Database(
version = 186, version = 187,
entities = { entities = {
EntityIdentity.class, EntityIdentity.class,
EntityAccount.class, EntityAccount.class,
@ -1823,6 +1823,14 @@ public abstract class DB extends RoomDatabase {
Log.i("DB migration from version " + startVersion + " to " + endVersion); Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `message` ADD COLUMN `return_path` TEXT"); db.execSQL("ALTER TABLE `message` ADD COLUMN `return_path` TEXT");
} }
})
.addMigrations(new Migration(186, 187) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `message` ADD COLUMN `deleted` INTEGER NOT NULL DEFAULT 0");
db.execSQL("ALTER TABLE `message` ADD COLUMN `ui_deleted` INTEGER NOT NULL DEFAULT 0");
}
}); });
} }

@ -646,6 +646,9 @@ public interface DaoMessage {
" AND (NOT (ui_flagged IS :ui_flagged) OR NOT (color IS :color))") " AND (NOT (ui_flagged IS :ui_flagged) OR NOT (color IS :color))")
int setMessageUiFlagged(long id, boolean ui_flagged, Integer color); int setMessageUiFlagged(long id, boolean ui_flagged, Integer color);
@Query("UPDATE message SET ui_deleted = :ui_deleted WHERE id = :id AND NOT (ui_deleted IS :ui_deleted)")
int setMessageUiDeleted(long id, boolean ui_deleted);
@Query("UPDATE message SET ui_answered = :ui_answered WHERE id = :id AND NOT (ui_answered IS :ui_answered)") @Query("UPDATE message SET ui_answered = :ui_answered WHERE id = :id AND NOT (ui_answered IS :ui_answered)")
int setMessageUiAnswered(long id, boolean ui_answered); int setMessageUiAnswered(long id, boolean ui_answered);

@ -188,6 +188,8 @@ public class EntityMessage implements Serializable {
public Boolean answered = false; public Boolean answered = false;
@NonNull @NonNull
public Boolean flagged = false; public Boolean flagged = false;
@NonNull
public Boolean deleted = false;
public String flags; // system flags public String flags; // system flags
public String[] keywords; // user flags public String[] keywords; // user flags
public String[] labels; // Gmail public String[] labels; // Gmail
@ -204,6 +206,8 @@ public class EntityMessage implements Serializable {
@NonNull @NonNull
public Boolean ui_flagged = false; public Boolean ui_flagged = false;
@NonNull @NonNull
public Boolean ui_deleted = false;
@NonNull
public Boolean ui_hide = false; public Boolean ui_hide = false;
@NonNull @NonNull
public Boolean ui_found = false; public Boolean ui_found = false;
@ -529,12 +533,14 @@ public class EntityMessage implements Serializable {
this.seen.equals(other.seen) && this.seen.equals(other.seen) &&
this.answered.equals(other.answered) && this.answered.equals(other.answered) &&
this.flagged.equals(other.flagged) && this.flagged.equals(other.flagged) &&
this.deleted.equals(other.deleted) &&
Objects.equals(this.flags, other.flags) && Objects.equals(this.flags, other.flags) &&
Helper.equal(this.keywords, other.keywords) && Helper.equal(this.keywords, other.keywords) &&
this.notifying.equals(other.notifying) && this.notifying.equals(other.notifying) &&
this.ui_seen.equals(other.ui_seen) && this.ui_seen.equals(other.ui_seen) &&
this.ui_answered.equals(other.ui_answered) && this.ui_answered.equals(other.ui_answered) &&
this.ui_flagged.equals(other.ui_flagged) && this.ui_flagged.equals(other.ui_flagged) &&
this.ui_deleted.equals(other.ui_deleted) &&
this.ui_hide.equals(other.ui_hide) && this.ui_hide.equals(other.ui_hide) &&
this.ui_found.equals(other.ui_found) && this.ui_found.equals(other.ui_found) &&
this.ui_ignored.equals(other.ui_ignored) && this.ui_ignored.equals(other.ui_ignored) &&

@ -224,7 +224,8 @@ public class EntityOperation {
if ((account != null && !account.isGmail()) || if ((account != null && !account.isGmail()) ||
!EntityFolder.ARCHIVE.equals(source.type) || !EntityFolder.ARCHIVE.equals(source.type) ||
EntityFolder.TRASH.equals(target.type) || EntityFolder.JUNK.equals(target.type)) EntityFolder.TRASH.equals(target.type) || EntityFolder.JUNK.equals(target.type))
db.message().setMessageUiHide(message.id, true); if (!message.ui_deleted)
db.message().setMessageUiHide(message.id, true);
if (account != null && account.isGmail() && if (account != null && account.isGmail() &&
EntityFolder.ARCHIVE.equals(source.type) && EntityFolder.ARCHIVE.equals(source.type) &&
@ -341,7 +342,12 @@ public class EntityOperation {
return; return;
} else if (DELETE.equals(name)) { } else if (DELETE.equals(name)) {
db.message().setMessageUiHide(message.id, true); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean perform_expunge = prefs.getBoolean("perform_expunge", true);
if (perform_expunge)
db.message().setMessageUiHide(message.id, true);
else
db.message().setMessageUiDeleted(message.id, true);
/* /*
if (message.hash != null) { if (message.hash != null) {
List<EntityMessage> sames = db.message().getMessagesByHash(message.account, message.hash); List<EntityMessage> sames = db.message().getMessagesByHash(message.account, message.hash);

@ -475,6 +475,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
@Override @Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("perform_expunge", checked).apply(); prefs.edit().putBoolean("perform_expunge", checked).apply();
ServiceSynchronize.reload(getContext(), null, true, "perform_expunge");
} }
}); });

@ -869,6 +869,10 @@ public class MessageHelper {
return imessage.isSet(Flags.Flag.FLAGGED); return imessage.isSet(Flags.Flag.FLAGGED);
} }
boolean getDeleted() throws MessagingException {
return imessage.isSet(Flags.Flag.DELETED);
}
String getFlags() throws MessagingException { String getFlags() throws MessagingException {
if (!BuildConfig.DEBUG) if (!BuildConfig.DEBUG)
return null; return null;

Loading…
Cancel
Save