Core keyword support

pull/146/head
M66B 6 years ago
parent 147bf957d8
commit a9d93929af

@ -102,6 +102,7 @@ The low priority status bar notification shows the number of pending operations,
* seen: mark message as seen/unseen in remote folder * seen: mark message as seen/unseen in remote folder
* answered: mark message as answered in remote folder * answered: mark message as answered in remote folder
* flag: add/remove star in remote folder * flag: add/remove star in remote folder
* keyword: add/remove IMAP flag in remote folder
* headers: download message headers * headers: download message headers
* body: download message text * body: download message text
* attachment: download attachment * attachment: download attachment

File diff suppressed because it is too large Load Diff

@ -46,7 +46,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
// https://developer.android.com/topic/libraries/architecture/room.html // https://developer.android.com/topic/libraries/architecture/room.html
@Database( @Database(
version = 7, version = 8,
entities = { entities = {
EntityIdentity.class, EntityIdentity.class,
EntityAccount.class, EntityAccount.class,
@ -170,18 +170,31 @@ public abstract class DB extends RoomDatabase {
db.execSQL("ALTER TABLE `message` ADD COLUMN `ui_answered` INTEGER NOT NULL DEFAULT 0"); db.execSQL("ALTER TABLE `message` ADD COLUMN `ui_answered` INTEGER NOT NULL DEFAULT 0");
} }
}) })
.addMigrations(new Migration(7, 8) {
@Override
public void migrate(SupportSQLiteDatabase db) {
Log.i(Helper.TAG, "DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `message` ADD COLUMN `keywords` TEXT");
}
})
.build(); .build();
} }
public static class Converters { public static class Converters {
@TypeConverter @TypeConverter
public static String[] fromStringArray(String value) { public static String[] toStringArray(String value) {
return value.split(","); if (value == null)
return new String[0];
else
return TextUtils.split(" ", value);
} }
@TypeConverter @TypeConverter
public static String toStringArray(String[] value) { public static String fromStringArray(String[] value) {
return TextUtils.join(",", value); if (value == null || value.length == 0)
return null;
else
return TextUtils.join(" ", value);
} }
@TypeConverter @TypeConverter

@ -252,21 +252,24 @@ public interface DaoMessage {
@Query("UPDATE message SET seen = :seen WHERE id = :id") @Query("UPDATE message SET seen = :seen WHERE id = :id")
int setMessageSeen(long id, boolean seen); int setMessageSeen(long id, boolean seen);
@Query("UPDATE message SET ui_seen = :ui_seen WHERE id = :id") @Query("UPDATE message SET flagged = :flagged WHERE id = :id")
int setMessageUiSeen(long id, boolean ui_seen); int setMessageFlagged(long id, boolean flagged);
@Query("UPDATE message SET answered = :answered WHERE id = :id") @Query("UPDATE message SET answered = :answered WHERE id = :id")
int setMessageAnswered(long id, boolean answered); int setMessageAnswered(long id, boolean answered);
@Query("UPDATE message SET ui_answered = :ui_answered WHERE id = :id") @Query("UPDATE message SET keywords = :keywords WHERE id = :id")
int setMessageUiAnswered(long id, boolean ui_answered); int setMessageKeywords(long id, String keywords);
@Query("UPDATE message SET flagged = :flagged WHERE id = :id") @Query("UPDATE message SET ui_seen = :ui_seen WHERE id = :id")
int setMessageFlagged(long id, boolean flagged); int setMessageUiSeen(long id, boolean ui_seen);
@Query("UPDATE message SET ui_flagged = :ui_flagged WHERE id = :id") @Query("UPDATE message SET ui_flagged = :ui_flagged WHERE id = :id")
int setMessageUiFlagged(long id, boolean ui_flagged); int setMessageUiFlagged(long id, boolean ui_flagged);
@Query("UPDATE message SET ui_answered = :ui_answered WHERE id = :id")
int setMessageUiAnswered(long id, boolean ui_answered);
@Query("UPDATE message SET ui_hide = :ui_hide WHERE id = :id") @Query("UPDATE message SET ui_hide = :ui_hide WHERE id = :id")
int setMessageUiHide(long id, boolean ui_hide); int setMessageUiHide(long id, boolean ui_hide);

@ -133,6 +133,7 @@ public class EntityMessage implements Serializable {
public Boolean ui_found; public Boolean ui_found;
@NonNull @NonNull
public Boolean ui_ignored; public Boolean ui_ignored;
public String[] keywords;
public String error; public String error;
public Long last_attempt; // send public Long last_attempt; // send

@ -65,16 +65,17 @@ public class EntityOperation {
@NonNull @NonNull
public Long created; public Long created;
public static final String SEEN = "seen";
public static final String ADD = "add"; public static final String ADD = "add";
public static final String MOVE = "move"; public static final String MOVE = "move";
public static final String DELETE = "delete"; public static final String DELETE = "delete";
public static final String SEND = "send"; public static final String SEND = "send";
public static final String SEEN = "seen";
public static final String ANSWERED = "answered"; public static final String ANSWERED = "answered";
public static final String FLAG = "flag";
public static final String KEYWORD = "keyword";
public static final String HEADERS = "headers"; public static final String HEADERS = "headers";
public static final String BODY = "body"; public static final String BODY = "body";
public static final String ATTACHMENT = "attachment"; public static final String ATTACHMENT = "attachment";
public static final String FLAG = "flag";
private static List<Intent> queue = new ArrayList<>(); private static List<Intent> queue = new ArrayList<>();

@ -434,4 +434,15 @@ public class Helper {
result.add(array[i]); result.add(array[i]);
return result; return result;
} }
static boolean equal(String[] a1, String[] a2) {
if (a1.length != a2.length)
return false;
for (int i = 0; i < a1.length; i++)
if (!a1[i].equals(a2[i]))
return false;
return true;
}
} }

@ -364,6 +364,10 @@ public class MessageHelper {
return imessage.isSet(Flags.Flag.FLAGGED); return imessage.isSet(Flags.Flag.FLAGGED);
} }
String[] getKeywords() throws MessagingException {
return imessage.getFlags().getUserFlags();
}
String getMessageID() throws MessagingException { String getMessageID() throws MessagingException {
return imessage.getHeader("Message-ID", null); return imessage.getHeader("Message-ID", null);
} }

@ -846,6 +846,8 @@ public class ServiceSynchronize extends LifecycleService {
db.folder().setFolderState(folder.id, "connected"); db.folder().setFolderState(folder.id, "connected");
db.folder().setFolderError(folder.id, null); db.folder().setFolderError(folder.id, null);
Log.i(Helper.TAG, account.name + " folder " + folder.name + " flags=" + ifolder.getPermanentFlags());
// Synchronize folder // Synchronize folder
Thread sync = new Thread(new Runnable() { Thread sync = new Thread(new Runnable() {
PowerManager.WakeLock wl = pm.newWakeLock( PowerManager.WakeLock wl = pm.newWakeLock(
@ -1354,6 +1356,9 @@ public class ServiceSynchronize extends LifecycleService {
else if (EntityOperation.FLAG.equals(op.name)) else if (EntityOperation.FLAG.equals(op.name))
doFlag(folder, ifolder, message, jargs, db); doFlag(folder, ifolder, message, jargs, db);
else if (EntityOperation.KEYWORD.equals(op.name))
doKeyword(folder, ifolder, message, jargs, db);
else if (EntityOperation.ADD.equals(op.name)) else if (EntityOperation.ADD.equals(op.name))
doAdd(folder, isession, ifolder, message, jargs, db); doAdd(folder, isession, ifolder, message, jargs, db);
@ -1463,6 +1468,27 @@ public class ServiceSynchronize extends LifecycleService {
db.message().setMessageFlagged(message.id, flagged); db.message().setMessageFlagged(message.id, flagged);
} }
private void doKeyword(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException, JSONException {
// Set/reset user flag
// https://tools.ietf.org/html/rfc3501#section-2.3.2
String keyword = jargs.getString(0);
boolean set = jargs.getBoolean(1);
Message imessage = ifolder.getMessageByUID(message.uid);
if (imessage == null)
throw new MessageRemovedException();
Flags flags = new Flags(keyword);
imessage.setFlags(flags, set);
List<String> keywords = new ArrayList<>(Arrays.asList(message.keywords));
if (set)
keywords.add(keyword);
else
keywords.remove(keyword);
db.message().setMessageKeywords(message.id, DB.Converters.fromStringArray(keywords.toArray(new String[0])));
}
private void doAdd(EntityFolder folder, Session isession, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException, JSONException, IOException { private void doAdd(EntityFolder folder, Session isession, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException, JSONException, IOException {
// Append message // Append message
MimeMessage imessage = MessageHelper.from(this, message, isession); MimeMessage imessage = MessageHelper.from(this, message, isession);
@ -1633,6 +1659,7 @@ public class ServiceSynchronize extends LifecycleService {
throw new MessageRemovedException(); throw new MessageRemovedException();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (BuildConfig.DEBUG)
sb.append(imessage.getFlags().toString()).append("\n"); sb.append(imessage.getFlags().toString()).append("\n");
Enumeration<Header> headers = imessage.getAllHeaders(); Enumeration<Header> headers = imessage.getAllHeaders();
@ -1933,6 +1960,7 @@ public class ServiceSynchronize extends LifecycleService {
boolean seen = helper.getSeen(); boolean seen = helper.getSeen();
boolean answered = helper.getAnsered(); boolean answered = helper.getAnsered();
boolean flagged = helper.getFlagged(); boolean flagged = helper.getFlagged();
String[] keywords = helper.getKeywords();
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
@ -2042,6 +2070,7 @@ public class ServiceSynchronize extends LifecycleService {
message.ui_hide = false; message.ui_hide = false;
message.ui_found = found; message.ui_found = found;
message.ui_ignored = false; message.ui_ignored = false;
message.keywords = keywords;
message.getAvatar(context); message.getAvatar(context);
message.id = db.message().insertMessage(message); message.id = db.message().insertMessage(message);
@ -2088,6 +2117,13 @@ public class ServiceSynchronize extends LifecycleService {
db.message().updateMessage(message); db.message().updateMessage(message);
Log.i(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid + " unhide"); Log.i(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid + " unhide");
} }
if (!Helper.equal(message.keywords, keywords)) {
message.keywords = keywords;
db.message().updateMessage(message);
Log.i(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid +
" keywords=" + TextUtils.join(" ", keywords));
}
} }
return message.id; return message.id;

Loading…
Cancel
Save