mirror of https://github.com/M66B/FairEmail.git
Prevent account/identity invalidation
This commit is contained in:
parent
4624ae2166
commit
6e5c89c365
|
@ -93,8 +93,60 @@ public class ApplicationEx extends Application {
|
||||||
|
|
||||||
DB db = DB.getInstance(this);
|
DB db = DB.getInstance(this);
|
||||||
|
|
||||||
|
db.account().liveAccountView().observeForever(new Observer<List<TupleAccountView>>() {
|
||||||
|
private List<TupleAccountView> last = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChanged(List<TupleAccountView> accounts) {
|
||||||
|
if (accounts == null)
|
||||||
|
accounts = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
if (last == null || last.size() != accounts.size())
|
||||||
|
changed = true;
|
||||||
|
else
|
||||||
|
for (int i = 0; i < accounts.size(); i++)
|
||||||
|
if (!accounts.get(i).equals(last.get(i))) {
|
||||||
|
changed = true;
|
||||||
|
last = accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
Log.i("Invalidating account view");
|
||||||
|
last = accounts;
|
||||||
|
db.getInvalidationTracker().notifyObserversByTableNames("account_view");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
db.identity().liveIdentityView().observeForever(new Observer<List<TupleIdentityView>>() {
|
||||||
|
private List<TupleIdentityView> last = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChanged(List<TupleIdentityView> identities) {
|
||||||
|
if (identities == null)
|
||||||
|
identities = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
if (last == null || last.size() != identities.size())
|
||||||
|
changed = true;
|
||||||
|
else
|
||||||
|
for (int i = 0; i < identities.size(); i++)
|
||||||
|
if (!identities.get(i).equals(last.get(i))) {
|
||||||
|
changed = true;
|
||||||
|
last = identities;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
Log.i("Invalidating identity view");
|
||||||
|
last = identities;
|
||||||
|
db.getInvalidationTracker().notifyObserversByTableNames("identity_view");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
db.folder().liveFolderView().observeForever(new Observer<List<TupleFolderView>>() {
|
db.folder().liveFolderView().observeForever(new Observer<List<TupleFolderView>>() {
|
||||||
List<TupleFolderView> last = null;
|
private List<TupleFolderView> last = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(List<TupleFolderView> folders) {
|
public void onChanged(List<TupleFolderView> folders) {
|
||||||
|
|
|
@ -75,6 +75,8 @@ import io.requery.android.database.sqlite.SQLiteDatabase;
|
||||||
EntityLog.class
|
EntityLog.class
|
||||||
},
|
},
|
||||||
views = {
|
views = {
|
||||||
|
TupleAccountView.class,
|
||||||
|
TupleIdentityView.class,
|
||||||
TupleFolderView.class
|
TupleFolderView.class
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -142,6 +144,8 @@ public abstract class DB extends RoomDatabase {
|
||||||
Field fmViewTables = InvalidationTracker.class.getDeclaredField("mViewTables");
|
Field fmViewTables = InvalidationTracker.class.getDeclaredField("mViewTables");
|
||||||
fmViewTables.setAccessible(true);
|
fmViewTables.setAccessible(true);
|
||||||
Map<String, Set<String>> mViewTables = (Map) fmViewTables.get(sInstance.getInvalidationTracker());
|
Map<String, Set<String>> mViewTables = (Map) fmViewTables.get(sInstance.getInvalidationTracker());
|
||||||
|
mViewTables.get("account_view").clear();
|
||||||
|
mViewTables.get("identity_view").clear();
|
||||||
mViewTables.get("folder_view").clear();
|
mViewTables.get("folder_view").clear();
|
||||||
Log.i("Disabled view invalidation");
|
Log.i("Disabled view invalidation");
|
||||||
} catch (ReflectiveOperationException ex) {
|
} catch (ReflectiveOperationException ex) {
|
||||||
|
@ -1313,6 +1317,8 @@ public abstract class DB extends RoomDatabase {
|
||||||
@Override
|
@Override
|
||||||
public void migrate(@NonNull SupportSQLiteDatabase db) {
|
public void migrate(@NonNull SupportSQLiteDatabase db) {
|
||||||
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
||||||
|
db.execSQL("CREATE VIEW IF NOT EXISTS `account_view` AS " + TupleAccountView.query);
|
||||||
|
db.execSQL("CREATE VIEW IF NOT EXISTS `identity_view` AS " + TupleIdentityView.query);
|
||||||
db.execSQL("CREATE VIEW IF NOT EXISTS `folder_view` AS " + TupleFolderView.query);
|
db.execSQL("CREATE VIEW IF NOT EXISTS `folder_view` AS " + TupleFolderView.query);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -91,6 +91,9 @@ public interface DaoAccount {
|
||||||
@Query("SELECT * FROM account WHERE id = :id")
|
@Query("SELECT * FROM account WHERE id = :id")
|
||||||
LiveData<EntityAccount> liveAccount(long id);
|
LiveData<EntityAccount> liveAccount(long id);
|
||||||
|
|
||||||
|
@Query(TupleAccountView.query)
|
||||||
|
LiveData<List<TupleAccountView>> liveAccountView();
|
||||||
|
|
||||||
@Query("SELECT account.id" +
|
@Query("SELECT account.id" +
|
||||||
", account.swipe_left, l.type AS left_type, l.name AS left_name" +
|
", account.swipe_left, l.type AS left_type, l.name AS left_name" +
|
||||||
", account.swipe_right, r.type AS right_type, r.name AS right_name" +
|
", account.swipe_right, r.type AS right_type, r.name AS right_name" +
|
||||||
|
|
|
@ -34,6 +34,9 @@ public interface DaoIdentity {
|
||||||
" WHERE NOT :synchronize OR account.synchronize")
|
" WHERE NOT :synchronize OR account.synchronize")
|
||||||
LiveData<List<TupleIdentityEx>> liveIdentities(boolean synchronize);
|
LiveData<List<TupleIdentityEx>> liveIdentities(boolean synchronize);
|
||||||
|
|
||||||
|
@Query(TupleIdentityView.query)
|
||||||
|
LiveData<List<TupleIdentityView>> liveIdentityView();
|
||||||
|
|
||||||
@Query("SELECT identity.*, account.name AS accountName FROM identity" +
|
@Query("SELECT identity.*, account.name AS accountName FROM identity" +
|
||||||
" JOIN account ON account.id = identity.account" +
|
" JOIN account ON account.id = identity.account" +
|
||||||
" JOIN folder ON folder.account = identity.account AND folder.type = '" + EntityFolder.DRAFTS + "'" +
|
" JOIN folder ON folder.account = identity.account AND folder.type = '" + EntityFolder.DRAFTS + "'" +
|
||||||
|
|
|
@ -62,8 +62,8 @@ public interface DaoMessage {
|
||||||
" OR (NOT :found AND folder.type = :type))" +
|
" OR (NOT :found AND folder.type = :type))" +
|
||||||
" THEN message.received ELSE 0 END) AS dummy" +
|
" THEN message.received ELSE 0 END) AS dummy" +
|
||||||
" FROM (SELECT * FROM message ORDER BY received DESC) AS message" +
|
" FROM (SELECT * FROM message ORDER BY received DESC) AS message" +
|
||||||
" JOIN account ON account.id = message.account" +
|
" JOIN account_view AS account ON account.id = message.account" +
|
||||||
" LEFT JOIN identity ON identity.id = message.identity" +
|
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
|
||||||
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
||||||
" WHERE account.`synchronize`" +
|
" WHERE account.`synchronize`" +
|
||||||
" AND (:threading OR (:type IS NULL AND (folder.unified OR :found)) OR (:type IS NOT NULL AND folder.type = :type))" +
|
" AND (:threading OR (:type IS NULL AND (folder.unified OR :found)) OR (:type IS NOT NULL AND folder.type = :type))" +
|
||||||
|
@ -110,8 +110,8 @@ public interface DaoMessage {
|
||||||
", SUM(message.total) AS totalSize" +
|
", SUM(message.total) AS totalSize" +
|
||||||
", MAX(CASE WHEN folder.id = :folder THEN message.received ELSE 0 END) AS dummy" +
|
", MAX(CASE WHEN folder.id = :folder THEN message.received ELSE 0 END) AS dummy" +
|
||||||
" FROM (SELECT * FROM message ORDER BY received DESC) AS message" +
|
" FROM (SELECT * FROM message ORDER BY received DESC) AS message" +
|
||||||
" JOIN account ON account.id = message.account" +
|
" JOIN account_view AS account ON account.id = message.account" +
|
||||||
" LEFT JOIN identity ON identity.id = message.identity" +
|
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
|
||||||
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
||||||
" JOIN folder_view AS f ON f.id = :folder" +
|
" JOIN folder_view AS f ON f.id = :folder" +
|
||||||
" WHERE (message.account = f.account OR " + is_outbox + ")" +
|
" WHERE (message.account = f.account OR " + is_outbox + ")" +
|
||||||
|
@ -155,8 +155,8 @@ public interface DaoMessage {
|
||||||
", 1 AS visible" +
|
", 1 AS visible" +
|
||||||
", message.total AS totalSize" +
|
", message.total AS totalSize" +
|
||||||
" FROM message" +
|
" FROM message" +
|
||||||
" JOIN account ON account.id = message.account" +
|
" JOIN account_view AS account ON account.id = message.account" +
|
||||||
" LEFT JOIN identity ON identity.id = message.identity" +
|
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
|
||||||
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
||||||
" WHERE message.account = :account" +
|
" WHERE message.account = :account" +
|
||||||
" AND message.thread = :thread" +
|
" AND message.thread = :thread" +
|
||||||
|
@ -181,7 +181,7 @@ public interface DaoMessage {
|
||||||
", COUNT(message.id) AS count" +
|
", COUNT(message.id) AS count" +
|
||||||
", SUM(message.ui_seen) AS seen" +
|
", SUM(message.ui_seen) AS seen" +
|
||||||
" FROM message" +
|
" FROM message" +
|
||||||
" JOIN account ON account.id = message.account" +
|
" JOIN account_view AS account ON account.id = message.account" +
|
||||||
" WHERE message.account = :account" +
|
" WHERE message.account = :account" +
|
||||||
" AND message.thread = :thread" +
|
" AND message.thread = :thread" +
|
||||||
" AND (:id IS NULL OR message.id = :id)" +
|
" AND (:id IS NULL OR message.id = :id)" +
|
||||||
|
@ -270,7 +270,7 @@ public interface DaoMessage {
|
||||||
|
|
||||||
@Query("SELECT message.*" +
|
@Query("SELECT message.*" +
|
||||||
" FROM message" +
|
" FROM message" +
|
||||||
" LEFT JOIN account ON account.id = message.account" +
|
" LEFT JOIN account_view AS account ON account.id = message.account" +
|
||||||
" WHERE account = :account" +
|
" WHERE account = :account" +
|
||||||
" AND thread = :thread" +
|
" AND thread = :thread" +
|
||||||
" AND (:id IS NULL OR message.id = :id)" +
|
" AND (:id IS NULL OR message.id = :id)" +
|
||||||
|
@ -309,8 +309,8 @@ public interface DaoMessage {
|
||||||
", 1 AS visible" +
|
", 1 AS visible" +
|
||||||
", message.total AS totalSize" +
|
", message.total AS totalSize" +
|
||||||
" FROM message" +
|
" FROM message" +
|
||||||
" JOIN account ON account.id = message.account" +
|
" JOIN account_view AS account ON account.id = message.account" +
|
||||||
" LEFT JOIN identity ON identity.id = message.identity" +
|
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
|
||||||
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
||||||
" WHERE message.id = :id")
|
" WHERE message.id = :id")
|
||||||
LiveData<TupleMessageEx> liveMessage(long id);
|
LiveData<TupleMessageEx> liveMessage(long id);
|
||||||
|
@ -318,7 +318,7 @@ public interface DaoMessage {
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT account.id AS account, COUNT(message.id) AS unseen, SUM(ABS(notifying)) AS notifying" +
|
@Query("SELECT account.id AS account, COUNT(message.id) AS unseen, SUM(ABS(notifying)) AS notifying" +
|
||||||
" FROM message" +
|
" FROM message" +
|
||||||
" JOIN account ON account.id = message.account" +
|
" JOIN account_view AS account ON account.id = message.account" +
|
||||||
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
||||||
" WHERE (:account IS NULL OR account.id = :account)" +
|
" WHERE (:account IS NULL OR account.id = :account)" +
|
||||||
" AND account.`synchronize`" +
|
" AND account.`synchronize`" +
|
||||||
|
@ -330,7 +330,7 @@ public interface DaoMessage {
|
||||||
|
|
||||||
@Query("SELECT :account AS account, COUNT(message.id) AS unseen, SUM(ABS(notifying)) AS notifying" +
|
@Query("SELECT :account AS account, COUNT(message.id) AS unseen, SUM(ABS(notifying)) AS notifying" +
|
||||||
" FROM message" +
|
" FROM message" +
|
||||||
" JOIN account ON account.id = message.account" +
|
" JOIN account_view AS account ON account.id = message.account" +
|
||||||
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
||||||
" WHERE (:account IS NULL OR account.id = :account)" +
|
" WHERE (:account IS NULL OR account.id = :account)" +
|
||||||
" AND account.`synchronize`" +
|
" AND account.`synchronize`" +
|
||||||
|
@ -354,8 +354,8 @@ public interface DaoMessage {
|
||||||
", 1 AS visible" +
|
", 1 AS visible" +
|
||||||
", message.total AS totalSize" +
|
", message.total AS totalSize" +
|
||||||
" FROM message" +
|
" FROM message" +
|
||||||
" JOIN account ON account.id = message.account" +
|
" JOIN account_view AS account ON account.id = message.account" +
|
||||||
" LEFT JOIN identity ON identity.id = message.identity" +
|
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
|
||||||
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
||||||
" WHERE account.`synchronize`" +
|
" WHERE account.`synchronize`" +
|
||||||
" AND folder.notify" +
|
" AND folder.notify" +
|
||||||
|
@ -381,7 +381,7 @@ public interface DaoMessage {
|
||||||
", COUNT(message.id) - SUM(message.ui_flagged) AS unflagged" +
|
", COUNT(message.id) - SUM(message.ui_flagged) AS unflagged" +
|
||||||
", MAX(message.received) AS dummy" +
|
", MAX(message.received) AS dummy" +
|
||||||
" FROM message" +
|
" FROM message" +
|
||||||
" JOIN account ON account.id = message.account" +
|
" JOIN account_view AS account ON account.id = message.account" +
|
||||||
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
" JOIN folder_view AS folder ON folder.id = message.folder" +
|
||||||
" WHERE account.`synchronize`" +
|
" WHERE account.`synchronize`" +
|
||||||
" AND ((:folder IS NULL AND folder.unified) OR folder.id = :folder)" +
|
" AND ((:folder IS NULL AND folder.unified) OR folder.id = :folder)" +
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package eu.faircode.email;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file is part of FairEmail.
|
||||||
|
|
||||||
|
FairEmail is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
FairEmail is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright 2018-2020 by Marcel Bokhorst (M66B)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.room.ColumnInfo;
|
||||||
|
import androidx.room.DatabaseView;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@DatabaseView(
|
||||||
|
viewName = "account_view",
|
||||||
|
value = TupleAccountView.query
|
||||||
|
)
|
||||||
|
public class TupleAccountView {
|
||||||
|
static final String query = "SELECT id, pop, name, color, synchronize, notify, auto_seen, created FROM account";
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Long id;
|
||||||
|
@NonNull
|
||||||
|
@ColumnInfo(name = "pop")
|
||||||
|
public Integer protocol;
|
||||||
|
public String name;
|
||||||
|
public Integer color;
|
||||||
|
@NonNull
|
||||||
|
public Boolean synchronize;
|
||||||
|
@NonNull
|
||||||
|
public Boolean notify = false;
|
||||||
|
@NonNull
|
||||||
|
public Boolean auto_seen = true;
|
||||||
|
public Long created;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object obj) {
|
||||||
|
if (obj instanceof TupleAccountView) {
|
||||||
|
TupleAccountView other = (TupleAccountView) obj;
|
||||||
|
return (this.id.equals(other.id) &&
|
||||||
|
this.protocol.equals(other.protocol) &&
|
||||||
|
Objects.equals(this.name, other.name) &&
|
||||||
|
Objects.equals(this.color, other.color) &&
|
||||||
|
this.synchronize.equals(other.synchronize) &&
|
||||||
|
this.notify.equals(other.notify) &&
|
||||||
|
this.auto_seen.equals(other.auto_seen) &&
|
||||||
|
Objects.equals(this.created, other.created));
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package eu.faircode.email;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file is part of FairEmail.
|
||||||
|
|
||||||
|
FairEmail is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
FairEmail is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright 2018-2020 by Marcel Bokhorst (M66B)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.room.DatabaseView;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@DatabaseView(
|
||||||
|
viewName = "identity_view",
|
||||||
|
value = TupleIdentityView.query
|
||||||
|
)
|
||||||
|
public class TupleIdentityView {
|
||||||
|
static final String query = "SELECT id, name, email, display, color, synchronize FROM identity";
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Long id;
|
||||||
|
@NonNull
|
||||||
|
public String name;
|
||||||
|
@NonNull
|
||||||
|
public String email;
|
||||||
|
public String display;
|
||||||
|
public Integer color;
|
||||||
|
@NonNull
|
||||||
|
public Boolean synchronize;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object obj) {
|
||||||
|
if (obj instanceof TupleIdentityView) {
|
||||||
|
TupleIdentityView other = (TupleIdentityView) obj;
|
||||||
|
return (this.id.equals(other.id) &&
|
||||||
|
this.name.equals(other.name) &&
|
||||||
|
this.email.equals(other.email) &&
|
||||||
|
Objects.equals(this.display, other.display) &&
|
||||||
|
Objects.equals(this.color, other.color) &&
|
||||||
|
this.synchronize.equals(other.synchronize));
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue