Improved search performance

pull/162/head
M66B 5 years ago
parent ebc40787ac
commit 822e4e3af7

@ -263,7 +263,8 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> {
return 0;
int applied = 0;
List<Long> ids = db.message().getMessageIdsByFolder(rule.folder);
List<Long> ids =
db.message().getMessageIdsByFolder(rule.folder, null, null, null);
for (long mid : ids)
try {
db.beginTransaction();

@ -35,6 +35,7 @@ import com.sun.mail.imap.IMAPMessage;
import com.sun.mail.imap.protocol.IMAPProtocol;
import com.sun.mail.imap.protocol.IMAPResponse;
import java.io.File;
import java.io.IOException;
import java.text.Normalizer;
import java.util.ArrayList;
@ -46,7 +47,6 @@ import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.mail.Address;
import javax.mail.FetchProfile;
import javax.mail.Flags;
import javax.mail.Folder;
@ -55,7 +55,6 @@ import javax.mail.Message;
import javax.mail.MessageRemovedException;
import javax.mail.MessagingException;
import javax.mail.UIDFolder;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.search.AndTerm;
import javax.mail.search.BodyTerm;
@ -165,74 +164,60 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
private int load_device(State state) {
DB db = DB.getInstance(context);
Boolean seen = null;
Boolean flagged = null;
Boolean snoozed = null;
String find = (TextUtils.isEmpty(query) ? null : query.toLowerCase(Locale.ROOT));
if (find != null && find.startsWith(context.getString(R.string.title_search_special_prefix) + ":")) {
String special = find.split(":")[1];
if (context.getString(R.string.title_search_special_unseen).equals(special))
seen = false;
else if (context.getString(R.string.title_search_special_flagged).equals(special))
flagged = true;
else if (context.getString(R.string.title_search_special_snoozed).equals(special))
snoozed = true;
}
if (state.messages == null) {
state.messages = db.message().getMessageIdsByFolder(folder);
Log.i("Boundary device folder=" + folder + " query=" + query + " messages=" + state.messages.size());
state.messages = db.message().getMessageIdsByFolder(folder, seen, flagged, snoozed);
Log.i("Boundary device folder=" + folder +
" query=" + query +
" seen=" + seen +
" flagged=" + flagged +
" snoozed=" + snoozed +
" messages=" + state.messages.size());
}
int found = 0;
try {
db.beginTransaction();
String find = (TextUtils.isEmpty(query) ? null : query.toLowerCase(Locale.ROOT));
for (int i = state.index; i < state.messages.size() && found < pageSize && !state.destroyed; i++) {
state.index = i + 1;
EntityMessage message = db.message().getMessage(state.messages.get(i));
if (message == null)
continue;
long id = state.messages.get(i);
EntityMessage message = null;
boolean match = false;
if (find == null)
match = true;
if (find == null || seen != null || flagged != null || snoozed != null)
message = db.message().getMessage(id);
else {
if (find.startsWith(context.getString(R.string.title_search_special_prefix) + ":")) {
String special = find.split(":")[1];
if (context.getString(R.string.title_search_special_unseen).equals(special))
match = !message.ui_seen;
else if (context.getString(R.string.title_search_special_flagged).equals(special))
match = message.ui_flagged;
else if (context.getString(R.string.title_search_special_snoozed).equals(special))
match = (message.ui_snoozed != null);
} else {
List<Address> addresses = new ArrayList<>();
if (message.from != null)
addresses.addAll(Arrays.asList(message.from));
if (message.to != null)
addresses.addAll(Arrays.asList(message.to));
if (message.cc != null)
addresses.addAll(Arrays.asList(message.cc));
for (Address address : addresses) {
String email = ((InternetAddress) address).getAddress();
String name = ((InternetAddress) address).getPersonal();
if (email != null && email.toLowerCase(Locale.ROOT).contains(find) ||
name != null && name.toLowerCase(Locale.ROOT).contains(find))
match = true;
}
if (!match && message.subject != null)
match = message.subject.toLowerCase(Locale.ROOT).contains(find);
if (!match && message.keywords != null && message.keywords.length > 0)
for (String keyword : message.keywords)
if (keyword.toLowerCase(Locale.ROOT).contains(find)) {
match = true;
break;
}
if (!match && message.content) {
try {
String body = Helper.readText(message.getFile(context));
match = body.toLowerCase(Locale.ROOT).contains(find);
} catch (IOException ex) {
Log.e(ex);
message = db.message().match(id, find);
if (message == null)
try {
File file = EntityMessage.getFile(context, id);
if (file.exists()) {
String body = Helper.readText(file);
if (body.toLowerCase(Locale.ROOT).contains(find))
message = db.message().getMessage(id);
}
} catch (IOException ex) {
Log.e(ex);
}
}
}
if (match) {
if (message != null) {
found++;
db.message().setMessageFound(message.account, message.thread);
}

@ -215,8 +215,14 @@ public interface DaoMessage {
" FROM message" +
" WHERE (:folder IS NULL OR folder = :folder)" +
" AND NOT ui_hide" +
" AND (:seen IS NULL OR message.ui_seen = :seen)" +
" AND (:flagged IS NULL OR message.ui_flagged = :flagged)" +
" AND CASE :snoozed" +
" WHEN 0 THEN message.ui_snoozed IS NULL" +
" WHEN 1 THEN message.ui_snoozed IS NOT NULL" +
" ELSE 1 END" + // NULL: true
" ORDER BY message.received DESC")
List<Long> getMessageIdsByFolder(Long folder);
List<Long> getMessageIdsByFolder(Long folder, Boolean seen, Boolean flagged, Boolean snoozed);
@Query("SELECT id" +
" FROM message" +
@ -363,6 +369,16 @@ public interface DaoMessage {
" WHERE folder = :folder")
Long getMessageOldest(long folder);
@Query("SELECT * FROM message" +
" WHERE id = :id" +
" AND (`from` LIKE :find COLLATE NOCASE" +
" OR `to` LIKE :find COLLATE NOCASE" +
" OR `cc` LIKE :find COLLATE NOCASE" +
" OR `subject` LIKE :find COLLATE NOCASE" +
" OR `keywords` LIKE :find COLLATE NOCASE" +
" OR `preview` LIKE :find COLLATE NOCASE)")
EntityMessage match(long id, String find);
@Insert
long insertMessage(EntityMessage message);

@ -1076,7 +1076,8 @@ public class FragmentRule extends FragmentBase {
int applied = 0;
DB db = DB.getInstance(context);
List<Long> ids = db.message().getMessageIdsByFolder(rule.folder);
List<Long> ids =
db.message().getMessageIdsByFolder(rule.folder, null, null, null);
for (long mid : ids)
try {
db.beginTransaction();
@ -1121,7 +1122,8 @@ public class FragmentRule extends FragmentBase {
List<EntityMessage> matching = new ArrayList<>();
DB db = DB.getInstance(context);
List<Long> ids = db.message().getMessageIdsByFolder(rule.folder);
List<Long> ids =
db.message().getMessageIdsByFolder(rule.folder, null, null, null);
for (long id : ids) {
EntityMessage message = db.message().getMessage(id);

@ -54,6 +54,7 @@ public class ViewModelMessages extends ViewModel {
private static final int LOCAL_PAGE_SIZE = 100;
private static final int REMOTE_PAGE_SIZE = 10;
private static final int SEARCH_PAGE_SIZE = 1;
private static final int LOW_MEM_MB = 32;
Model getModel(
@ -77,10 +78,13 @@ public class ViewModelMessages extends ViewModel {
DB db = DB.getInstance(context);
BoundaryCallbackMessages boundary = null;
if (viewType == AdapterMessage.ViewType.FOLDER || viewType == AdapterMessage.ViewType.SEARCH)
if (viewType == AdapterMessage.ViewType.FOLDER)
boundary = new BoundaryCallbackMessages(context,
args.folder, args.server || viewType == AdapterMessage.ViewType.FOLDER,
args.query, REMOTE_PAGE_SIZE);
args.folder, true, args.query, REMOTE_PAGE_SIZE);
else if (viewType == AdapterMessage.ViewType.SEARCH)
boundary = new BoundaryCallbackMessages(context,
args.folder, args.server, args.query,
args.server ? REMOTE_PAGE_SIZE : SEARCH_PAGE_SIZE);
LivePagedListBuilder<Integer, TupleMessageEx> builder = null;
switch (viewType) {

Loading…
Cancel
Save