Added conditional searching via search index

This commit is contained in:
M66B 2021-10-10 14:49:07 +02:00
parent e934a04ae6
commit ec3a6170d1
6 changed files with 108 additions and 16 deletions

View File

@ -7,6 +7,7 @@
### Next version ### Next version
* Added multiple select spam / block sender * Added multiple select spam / block sender
* Added conditional searching via search index
* Small improvements and minor bug fixes * Small improvements and minor bug fixes
* Updated translations * Updated translations

View File

@ -7,6 +7,7 @@
### Next version ### Next version
* Added multiple select spam / block sender * Added multiple select spam / block sender
* Added conditional searching via search index
* Small improvements and minor bug fixes * Small improvements and minor bug fixes
* Updated translations * Updated translations

View File

@ -58,6 +58,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.mail.Address;
import javax.mail.FetchProfile; import javax.mail.FetchProfile;
import javax.mail.Flags; import javax.mail.Flags;
import javax.mail.Folder; import javax.mail.Folder;
@ -269,6 +270,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
} }
int found = 0; int found = 0;
String query = (criteria.query == null ? null : criteria.query.toLowerCase());
if (criteria.fts && criteria.query != null) { if (criteria.fts && criteria.query != null) {
if (state.ids == null) { if (state.ids == null) {
@ -286,6 +288,99 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
for (; state.index < state.ids.size() && found < pageSize && !state.destroyed; state.index++) { for (; state.index < state.ids.size() && found < pageSize && !state.destroyed; state.index++) {
long id = state.ids.get(state.index); long id = state.ids.get(state.index);
EntityMessage message = db.message().getMessage(id);
if (message == null)
continue;
if (criteria.with_unseen) {
if (message.ui_seen)
continue;
}
if (criteria.with_flagged) {
if (!message.ui_flagged)
continue;
}
if (criteria.with_hidden) {
if (message.ui_snoozed == null)
continue;
}
if (criteria.with_encrypted) {
if (message.encrypt == null ||
EntityMessage.ENCRYPT_NONE.equals(message.encrypt))
continue;
}
boolean matched = false;
if (criteria.in_senders) {
if (contains(message.from, query))
matched = true;
}
if (criteria.in_recipients) {
if (contains(message.to, query) ||
contains(message.cc, query) ||
contains(message.bcc, query))
matched = true;
}
if (criteria.in_subject) {
if (message.subject != null &&
message.subject.toLowerCase().contains(query))
matched = true;
}
if (criteria.in_keywords) {
if (message.keywords != null)
for (String keyword : message.keywords)
if (keyword.toLowerCase().contains(query)) {
matched = true;
break;
}
}
if (criteria.in_notes) {
if (message.notes != null &&
message.notes.toLowerCase().contains(query))
matched = true;
}
if (!matched && criteria.in_message)
try {
File file = EntityMessage.getFile(context, id);
if (file.exists()) {
String html = Helper.readText(file);
if (html.toLowerCase().contains(query)) {
String text = HtmlHelper.getFullText(html);
if (text != null &&
text.toLowerCase().contains(query))
matched = true;
}
}
} catch (IOException ex) {
Log.e(ex);
}
if (!criteria.in_trash || !criteria.in_junk) {
EntityFolder folder = db.folder().getFolder(message.folder);
if (folder == null)
continue;
if (!criteria.in_trash) {
if (EntityFolder.TRASH.equals(folder.type))
continue;
}
if (!criteria.in_junk) {
if (EntityFolder.JUNK.equals(folder.type))
continue;
}
}
if (!matched)
continue;
found += db.message().setMessageFound(id); found += db.message().setMessageFound(id);
Log.i("Boundary matched=" + id + " found=" + found); Log.i("Boundary matched=" + id + " found=" + found);
} }
@ -336,8 +431,6 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
if (state.matches.size() == 0) if (state.matches.size() == 0)
break; break;
String query = (criteria.query == null ? null : criteria.query.toLowerCase());
for (int i = state.index; i < state.matches.size() && found < pageSize && !state.destroyed; i++) { for (int i = state.index; i < state.matches.size() && found < pageSize && !state.destroyed; i++) {
state.index = i + 1; state.index = i + 1;
@ -660,6 +753,15 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
return imessages; return imessages;
} }
private static boolean contains(Address[] addresses, String text) {
if (addresses == null)
return false;
for (Address address : addresses)
if (address.toString().toLowerCase().contains(text))
return true;
return false;
}
State getState() { State getState() {
return this.state; return this.state;
} }

View File

@ -253,18 +253,8 @@ public class FragmentDialogSearch extends FragmentDialogBase {
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
prefs.edit().putBoolean("last_fts", isChecked).apply(); prefs.edit().putBoolean("last_fts", isChecked).apply();
cbSenders.setAlpha(isChecked ? Helper.LOW_LIGHT : 1.0f);
cbRecipients.setAlpha(isChecked ? Helper.LOW_LIGHT : 1.0f);
cbSubject.setAlpha(isChecked ? Helper.LOW_LIGHT : 1.0f);
cbKeywords.setAlpha(isChecked ? Helper.LOW_LIGHT : 1.0f);
cbMessage.setAlpha(isChecked ? Helper.LOW_LIGHT : 1.0f);
cbNotes.setEnabled(!isChecked);
cbHeaders.setEnabled(!isChecked); cbHeaders.setEnabled(!isChecked);
cbHtml.setEnabled(!isChecked); cbHtml.setEnabled(!isChecked);
cbUnseen.setAlpha(isChecked ? Helper.LOW_LIGHT : 1.0f);
cbFlagged.setAlpha(isChecked ? Helper.LOW_LIGHT : 1.0f);
cbHidden.setEnabled(!isChecked);
cbEncrypted.setEnabled(!isChecked);
cbAttachments.setEnabled(!isChecked); cbAttachments.setEnabled(!isChecked);
spMessageSize.setEnabled(!isChecked); spMessageSize.setEnabled(!isChecked);
} }

View File

@ -1307,10 +1307,7 @@
Initially, the search is performed on the device. Initially, the search is performed on the device.
To search the server too, tap the \'search again\' button. To search the server too, tap the \'search again\' button.
</string> </string>
<string name="title_search_index_hint"> <string name="title_search_index_hint">Searching via the search index is fast, but only finds whole words.</string>
Searching via the search index is fast, but only finds whole words in all message parts.
The options below are to continue searching the email server.
</string>
<string name="title_search_text_hint">Searching for text in messages, when there are a large number of messages, might not work on some servers</string> <string name="title_search_text_hint">Searching for text in messages, when there are a large number of messages, might not work on some servers</string>
<string name="title_search_text_unsupported">\'%s\' means that the mail server doesn\'t support searching in message texts</string> <string name="title_search_text_unsupported">\'%s\' means that the mail server doesn\'t support searching in message texts</string>
<string name="title_search_size_hint">Searching for messages by size, when there are a large number of messages, might not work on some servers</string> <string name="title_search_size_hint">Searching for messages by size, when there are a large number of messages, might not work on some servers</string>

View File

@ -7,6 +7,7 @@
### Next version ### Next version
* Added multiple select spam / block sender * Added multiple select spam / block sender
* Added conditional searching via search index
* Small improvements and minor bug fixes * Small improvements and minor bug fixes
* Updated translations * Updated translations