Prevent account/identity invalidation

This commit is contained in:
M66B 2020-01-22 19:53:17 +01:00
parent 4624ae2166
commit 6e5c89c365
7 changed files with 205 additions and 16 deletions

View File

@ -93,8 +93,60 @@ public class ApplicationEx extends Application {
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>>() {
List<TupleFolderView> last = null;
private List<TupleFolderView> last = null;
@Override
public void onChanged(List<TupleFolderView> folders) {

View File

@ -75,6 +75,8 @@ import io.requery.android.database.sqlite.SQLiteDatabase;
EntityLog.class
},
views = {
TupleAccountView.class,
TupleIdentityView.class,
TupleFolderView.class
}
)
@ -142,6 +144,8 @@ public abstract class DB extends RoomDatabase {
Field fmViewTables = InvalidationTracker.class.getDeclaredField("mViewTables");
fmViewTables.setAccessible(true);
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();
Log.i("Disabled view invalidation");
} catch (ReflectiveOperationException ex) {
@ -1313,6 +1317,8 @@ public abstract class DB extends RoomDatabase {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {
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);
}
});

View File

@ -91,6 +91,9 @@ public interface DaoAccount {
@Query("SELECT * FROM account WHERE id = :id")
LiveData<EntityAccount> liveAccount(long id);
@Query(TupleAccountView.query)
LiveData<List<TupleAccountView>> liveAccountView();
@Query("SELECT account.id" +
", 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" +

View File

@ -34,6 +34,9 @@ public interface DaoIdentity {
" WHERE NOT :synchronize OR account.synchronize")
LiveData<List<TupleIdentityEx>> liveIdentities(boolean synchronize);
@Query(TupleIdentityView.query)
LiveData<List<TupleIdentityView>> liveIdentityView();
@Query("SELECT identity.*, account.name AS accountName FROM identity" +
" JOIN account ON account.id = identity.account" +
" JOIN folder ON folder.account = identity.account AND folder.type = '" + EntityFolder.DRAFTS + "'" +

View File

@ -62,8 +62,8 @@ public interface DaoMessage {
" OR (NOT :found AND folder.type = :type))" +
" THEN message.received ELSE 0 END) AS dummy" +
" FROM (SELECT * FROM message ORDER BY received DESC) AS message" +
" JOIN account ON account.id = message.account" +
" LEFT JOIN identity ON identity.id = message.identity" +
" JOIN account_view AS account ON account.id = message.account" +
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
" JOIN folder_view AS folder ON folder.id = message.folder" +
" WHERE account.`synchronize`" +
" 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" +
", MAX(CASE WHEN folder.id = :folder THEN message.received ELSE 0 END) AS dummy" +
" FROM (SELECT * FROM message ORDER BY received DESC) AS message" +
" JOIN account ON account.id = message.account" +
" LEFT JOIN identity ON identity.id = message.identity" +
" JOIN account_view AS account ON account.id = message.account" +
" 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 f ON f.id = :folder" +
" WHERE (message.account = f.account OR " + is_outbox + ")" +
@ -155,8 +155,8 @@ public interface DaoMessage {
", 1 AS visible" +
", message.total AS totalSize" +
" FROM message" +
" JOIN account ON account.id = message.account" +
" LEFT JOIN identity ON identity.id = message.identity" +
" JOIN account_view AS account ON account.id = message.account" +
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
" JOIN folder_view AS folder ON folder.id = message.folder" +
" WHERE message.account = :account" +
" AND message.thread = :thread" +
@ -181,7 +181,7 @@ public interface DaoMessage {
", COUNT(message.id) AS count" +
", SUM(message.ui_seen) AS seen" +
" FROM message" +
" JOIN account ON account.id = message.account" +
" JOIN account_view AS account ON account.id = message.account" +
" WHERE message.account = :account" +
" AND message.thread = :thread" +
" AND (:id IS NULL OR message.id = :id)" +
@ -270,7 +270,7 @@ public interface DaoMessage {
@Query("SELECT 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" +
" AND thread = :thread" +
" AND (:id IS NULL OR message.id = :id)" +
@ -309,8 +309,8 @@ public interface DaoMessage {
", 1 AS visible" +
", message.total AS totalSize" +
" FROM message" +
" JOIN account ON account.id = message.account" +
" LEFT JOIN identity ON identity.id = message.identity" +
" JOIN account_view AS account ON account.id = message.account" +
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
" JOIN folder_view AS folder ON folder.id = message.folder" +
" WHERE message.id = :id")
LiveData<TupleMessageEx> liveMessage(long id);
@ -318,7 +318,7 @@ public interface DaoMessage {
@Transaction
@Query("SELECT account.id AS account, COUNT(message.id) AS unseen, SUM(ABS(notifying)) AS notifying" +
" 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" +
" WHERE (:account IS NULL OR account.id = :account)" +
" 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" +
" 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" +
" WHERE (:account IS NULL OR account.id = :account)" +
" AND account.`synchronize`" +
@ -354,8 +354,8 @@ public interface DaoMessage {
", 1 AS visible" +
", message.total AS totalSize" +
" FROM message" +
" JOIN account ON account.id = message.account" +
" LEFT JOIN identity ON identity.id = message.identity" +
" JOIN account_view AS account ON account.id = message.account" +
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
" JOIN folder_view AS folder ON folder.id = message.folder" +
" WHERE account.`synchronize`" +
" AND folder.notify" +
@ -381,7 +381,7 @@ public interface DaoMessage {
", COUNT(message.id) - SUM(message.ui_flagged) AS unflagged" +
", MAX(message.received) AS dummy" +
" 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" +
" WHERE account.`synchronize`" +
" AND ((:folder IS NULL AND folder.unified) OR folder.id = :folder)" +

View File

@ -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;
}
}

View File

@ -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;
}
}