mirror of https://github.com/M66B/FairEmail.git
Support for IMAP answered flag
This commit is contained in:
parent
cdd34e26f7
commit
5246629f67
4
FAQ.md
4
FAQ.md
|
@ -22,7 +22,6 @@ For:
|
|||
|
||||
## Planned features
|
||||
|
||||
* IMAP answered flag
|
||||
* IMAP namespaces
|
||||
* Microsoft OAuth ([blocking issue](https://github.com/AzureAD/microsoft-authentication-library-for-android/issues/354))
|
||||
|
||||
|
@ -101,7 +100,8 @@ The low priority status bar notification shows the number of pending operations,
|
|||
* delete: delete message from remote folder
|
||||
* send: send message
|
||||
* seen: mark message as seen/unseen in remote folder
|
||||
* flag: add/remove stars
|
||||
* answered: mark message as answered in remote folder
|
||||
* flag: add/remove star in remote folder
|
||||
* headers: download message headers
|
||||
* body: download message text
|
||||
* attachment: download attachment
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -141,6 +141,7 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
|
|||
private TextView tvFrom;
|
||||
private TextView tvSize;
|
||||
private TextView tvTime;
|
||||
private ImageView ivAnswered;
|
||||
private ImageView ivAttachments;
|
||||
private TextView tvSubject;
|
||||
private TextView tvFolder;
|
||||
|
@ -196,6 +197,7 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
|
|||
tvTime = itemView.findViewById(R.id.tvTime);
|
||||
tvTimeSent = itemView.findViewById(R.id.tvTimeSent);
|
||||
tvTimeReceived = itemView.findViewById(R.id.tvTimeReceived);
|
||||
ivAnswered = itemView.findViewById(R.id.ivAnswered);
|
||||
ivAttachments = itemView.findViewById(R.id.ivAttachments);
|
||||
tvSubject = itemView.findViewById(R.id.tvSubject);
|
||||
tvPreview = itemView.findViewById(R.id.tvPreview);
|
||||
|
@ -273,6 +275,7 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
|
|||
ivAddContact.setVisibility(View.GONE);
|
||||
tvSize.setText(null);
|
||||
tvTime.setText(null);
|
||||
ivAnswered.setVisibility(View.GONE);
|
||||
ivAttachments.setVisibility(View.GONE);
|
||||
tvSubject.setText(null);
|
||||
tvFolder.setText(null);
|
||||
|
@ -346,6 +349,7 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
|
|||
tvSize.setAlpha(message.content ? 1.0f : 0.5f);
|
||||
tvSize.setVisibility(message.size == null ? View.GONE : View.VISIBLE);
|
||||
|
||||
ivAnswered.setVisibility(message.ui_answered ? View.VISIBLE : View.GONE);
|
||||
ivAttachments.setVisibility(message.attachments > 0 ? View.VISIBLE : View.GONE);
|
||||
tvSubject.setText(message.subject);
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
|
|||
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||
|
||||
@Database(
|
||||
version = 6,
|
||||
version = 7,
|
||||
entities = {
|
||||
EntityIdentity.class,
|
||||
EntityAccount.class,
|
||||
|
@ -162,6 +162,14 @@ public abstract class DB extends RoomDatabase {
|
|||
db.execSQL("ALTER TABLE `account` ADD COLUMN `notify` INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
})
|
||||
.addMigrations(new Migration(6, 7) {
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase db) {
|
||||
Log.i(Helper.TAG, "DB migration from version " + startVersion + " to " + endVersion);
|
||||
db.execSQL("ALTER TABLE `message` ADD COLUMN `answered` INTEGER NOT NULL DEFAULT 0");
|
||||
db.execSQL("ALTER TABLE `message` ADD COLUMN `ui_answered` INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -255,6 +255,12 @@ public interface DaoMessage {
|
|||
@Query("UPDATE message SET ui_seen = :ui_seen WHERE id = :id")
|
||||
int setMessageUiSeen(long id, boolean ui_seen);
|
||||
|
||||
@Query("UPDATE message SET answered = :answered WHERE id = :id")
|
||||
int setMessageAnswered(long id, boolean answered);
|
||||
|
||||
@Query("UPDATE message SET ui_answered = :ui_answered WHERE id = :id")
|
||||
int setMessageUiAnswered(long id, boolean ui_answered);
|
||||
|
||||
@Query("UPDATE message SET flagged = :flagged WHERE id = :id")
|
||||
int setMessageFlagged(long id, boolean flagged);
|
||||
|
||||
|
|
|
@ -118,10 +118,14 @@ public class EntityMessage implements Serializable {
|
|||
@NonNull
|
||||
public Boolean seen;
|
||||
@NonNull
|
||||
public Boolean answered;
|
||||
@NonNull
|
||||
public Boolean flagged;
|
||||
@NonNull
|
||||
public Boolean ui_seen;
|
||||
@NonNull
|
||||
public Boolean ui_answered;
|
||||
@NonNull
|
||||
public Boolean ui_flagged;
|
||||
@NonNull
|
||||
public Boolean ui_hide;
|
||||
|
@ -272,8 +276,10 @@ public class EntityMessage implements Serializable {
|
|||
this.received.equals(other.received) &&
|
||||
this.stored.equals(other.stored) &&
|
||||
this.seen.equals(other.seen) &&
|
||||
this.answered.equals(other.answered) &&
|
||||
this.flagged.equals(other.flagged) &&
|
||||
this.ui_seen.equals(other.ui_seen) &&
|
||||
this.ui_answered.equals(other.ui_answered) &&
|
||||
this.ui_flagged.equals(other.ui_flagged) &&
|
||||
this.ui_hide.equals(other.ui_hide) &&
|
||||
this.ui_found.equals(other.ui_found) &&
|
||||
|
|
|
@ -70,6 +70,7 @@ public class EntityOperation {
|
|||
public static final String MOVE = "move";
|
||||
public static final String DELETE = "delete";
|
||||
public static final String SEND = "send";
|
||||
public static final String ANSWERED = "answered";
|
||||
public static final String HEADERS = "headers";
|
||||
public static final String BODY = "body";
|
||||
public static final String ATTACHMENT = "attachment";
|
||||
|
|
|
@ -1205,8 +1205,10 @@ public class FragmentCompose extends FragmentEx {
|
|||
result.draft.content = true;
|
||||
result.draft.received = new Date().getTime();
|
||||
result.draft.seen = false;
|
||||
result.draft.ui_seen = false;
|
||||
result.draft.answered = false;
|
||||
result.draft.flagged = false;
|
||||
result.draft.ui_seen = false;
|
||||
result.draft.ui_answered = false;
|
||||
result.draft.ui_flagged = false;
|
||||
result.draft.ui_hide = false;
|
||||
result.draft.ui_found = false;
|
||||
|
@ -1640,6 +1642,12 @@ public class FragmentCompose extends FragmentEx {
|
|||
}
|
||||
|
||||
EntityOperation.queue(db, draft, EntityOperation.SEND);
|
||||
|
||||
if (draft.replying != null) {
|
||||
EntityMessage replying = db.message().getMessage(draft.replying);
|
||||
db.message().setMessageUiAnswered(replying.id, true);
|
||||
EntityOperation.queue(db, replying, EntityOperation.ANSWERED, true);
|
||||
}
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
|
|
|
@ -356,6 +356,10 @@ public class MessageHelper {
|
|||
return imessage.isSet(Flags.Flag.SEEN);
|
||||
}
|
||||
|
||||
boolean getAnsered() throws MessagingException {
|
||||
return imessage.isSet(Flags.Flag.ANSWERED);
|
||||
}
|
||||
|
||||
boolean getFlagged() throws MessagingException {
|
||||
return imessage.isSet(Flags.Flag.FLAGGED);
|
||||
}
|
||||
|
|
|
@ -1348,6 +1348,9 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
if (EntityOperation.SEEN.equals(op.name))
|
||||
doSeen(folder, ifolder, message, jargs, db);
|
||||
|
||||
else if (EntityOperation.ANSWERED.equals(op.name))
|
||||
doAnswered(folder, ifolder, message, jargs, db);
|
||||
|
||||
else if (EntityOperation.FLAG.equals(op.name))
|
||||
doFlag(folder, ifolder, message, jargs, db);
|
||||
|
||||
|
@ -1430,6 +1433,21 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
db.message().setMessageSeen(message.id, seen);
|
||||
}
|
||||
|
||||
private void doAnswered(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException, JSONException {
|
||||
// Mark message (un)answered
|
||||
boolean answered = jargs.getBoolean(0);
|
||||
if (message.answered != answered)
|
||||
return;
|
||||
|
||||
Message imessage = ifolder.getMessageByUID(message.uid);
|
||||
if (imessage == null)
|
||||
throw new MessageRemovedException();
|
||||
|
||||
imessage.setFlag(Flags.Flag.ANSWERED, answered);
|
||||
|
||||
db.message().setMessageAnswered(message.id, answered);
|
||||
}
|
||||
|
||||
private void doFlag(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException, JSONException {
|
||||
// Star/unstar message
|
||||
boolean flagged = jargs.getBoolean(0);
|
||||
|
@ -1907,6 +1925,7 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
|
||||
MessageHelper helper = new MessageHelper(imessage);
|
||||
boolean seen = helper.getSeen();
|
||||
boolean answered = helper.getAnsered();
|
||||
boolean flagged = helper.getFlagged();
|
||||
|
||||
DB db = DB.getInstance(context);
|
||||
|
@ -2009,8 +2028,10 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
message.received = imessage.getReceivedDate().getTime();
|
||||
message.sent = (imessage.getSentDate() == null ? null : imessage.getSentDate().getTime());
|
||||
message.seen = seen;
|
||||
message.ui_seen = seen;
|
||||
message.answered = answered;
|
||||
message.flagged = false;
|
||||
message.ui_seen = seen;
|
||||
message.ui_answered = answered;
|
||||
message.ui_flagged = false;
|
||||
message.ui_hide = false;
|
||||
message.ui_found = found;
|
||||
|
@ -2042,6 +2063,13 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
Log.i(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid + " seen=" + seen);
|
||||
}
|
||||
|
||||
if (message.answered != answered || message.answered != message.ui_answered) {
|
||||
message.answered = answered;
|
||||
message.ui_answered = answered;
|
||||
db.message().updateMessage(message);
|
||||
Log.i(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid + " answered=" + answered);
|
||||
}
|
||||
|
||||
if (message.flagged != flagged || message.flagged != message.ui_flagged) {
|
||||
message.flagged = flagged;
|
||||
message.ui_flagged = flagged;
|
||||
|
|
|
@ -108,6 +108,16 @@
|
|||
app:layout_constraintEnd_toStartOf="@+id/paddingEnd"
|
||||
app:layout_constraintTop_toTopOf="@id/tvFrom" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivAnswered"
|
||||
android:layout_width="21dp"
|
||||
android:layout_height="21dp"
|
||||
android:layout_marginStart="6dp"
|
||||
android:src="@drawable/baseline_reply_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tvSubject"
|
||||
app:layout_constraintStart_toEndOf="@id/paddingStart"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvSubject" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivAttachments"
|
||||
android:layout_width="21dp"
|
||||
|
@ -115,7 +125,7 @@
|
|||
android:layout_marginStart="6dp"
|
||||
android:src="@drawable/baseline_attachment_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tvSubject"
|
||||
app:layout_constraintStart_toEndOf="@id/paddingStart"
|
||||
app:layout_constraintStart_toEndOf="@id/ivAnswered"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvSubject" />
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -105,6 +105,16 @@
|
|||
app:layout_constraintEnd_toStartOf="@+id/paddingEnd"
|
||||
app:layout_constraintTop_toTopOf="@id/tvFrom" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivAnswered"
|
||||
android:layout_width="21dp"
|
||||
android:layout_height="21dp"
|
||||
android:layout_marginStart="6dp"
|
||||
android:src="@drawable/baseline_reply_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tvSubject"
|
||||
app:layout_constraintStart_toEndOf="@id/paddingStart"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvSubject" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivAttachments"
|
||||
android:layout_width="21dp"
|
||||
|
@ -112,7 +122,7 @@
|
|||
android:layout_marginStart="6dp"
|
||||
android:src="@drawable/baseline_attachment_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tvSubject"
|
||||
app:layout_constraintStart_toEndOf="@id/paddingStart"
|
||||
app:layout_constraintStart_toEndOf="@id/ivAnswered"
|
||||
app:layout_constraintTop_toTopOf="@+id/tvSubject" />
|
||||
|
||||
<TextView
|
||||
|
|
Loading…
Reference in New Issue