Added local search

pull/146/head
M66B 6 years ago
parent 4a0326f431
commit bcc97c3e08

@ -14,7 +14,6 @@ Frequently requested features:
* Executing filter rules: filter rules should be executed on the server because a battery powered device with possibly an unstable internet connection is not suitable for this. * Executing filter rules: filter rules should be executed on the server because a battery powered device with possibly an unstable internet connection is not suitable for this.
* Widget to read e-mail: widgets do not allow user interaction, so a widget to read e-mail would not be very useful. * Widget to read e-mail: widgets do not allow user interaction, so a widget to read e-mail would not be very useful.
* Swipe left/right to go to previous/next message: swiping also selects message text, so this would not work reliably. * Swipe left/right to go to previous/next message: swiping also selects message text, so this would not work reliably.
* Local search: searching on the server is almost always faster and using less battery power.
Since FairEmail is meant to be privacy friendly, the following will not be added: Since FairEmail is meant to be privacy friendly, the following will not be added:
@ -141,9 +140,11 @@ To encrypt a message before sending, just select the menu *Encrypt*. Similarly,
**(13) How does search on server work?** **(13) How does search on server work?**
You can start searching for messages on sender, recipient, subject or message text by using the magnify glass in the action bar of a folder (not in the unified inbox because it could be a collection of folders). You can start searching for messages on sender, recipient, subject or message text by using the magnify glass in the action bar of a folder (not in the unified inbox because it could be a collection of folders).
The server executes the search. Scrolling down will fetch more messages from the server. First local messages will be searched and after that the server will execute the search.
Searching local messages is case insensitive and on partial text.
The message text of local messages will not be searched if the message text was not downloaded yet.
Searching by the server might be case sensitive or case insensitive and might be on partial text or whole words, depending on the provider. Searching by the server might be case sensitive or case insensitive and might be on partial text or whole words, depending on the provider.
Search on server is a pro feature. Searching messages is a pro feature.
<a name="FAQ14"></a> <a name="FAQ14"></a>
**(14) How can I setup Outlook with 2FA?** **(14) How can I setup Outlook with 2FA?**

@ -239,7 +239,8 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
try { try {
db.beginTransaction(); db.beginTransaction();
for (EntityMessage message : db.message().getMessageByFolder(id)) { for (Long mid : db.message().getMessageByFolder(id)) {
EntityMessage message = db.message().getMessage(mid);
db.message().setMessageUiHide(message.id, true); db.message().setMessageUiHide(message.id, true);
EntityOperation.queue(db, message, EntityOperation.DELETE); EntityOperation.queue(db, message, EntityOperation.DELETE);
} }

@ -131,11 +131,12 @@ public interface DaoMessage {
" AND ui_found = :found") " AND ui_found = :found")
EntityMessage getMessageByUid(long folder, long uid, boolean found); EntityMessage getMessageByUid(long folder, long uid, boolean found);
@Query("SELECT *" + @Query("SELECT id" +
" FROM message" + " FROM message" +
" WHERE folder = :folder" + " WHERE folder = :folder" +
" AND NOT ui_found") " AND NOT ui_found" +
List<EntityMessage> getMessageByFolder(long folder); " ORDER BY message.received DESC, message.sent DESC")
List<Long> getMessageByFolder(long folder);
@Query("SELECT *" + @Query("SELECT *" +
" FROM message" + " FROM message" +

@ -27,7 +27,9 @@ import com.sun.mail.imap.IMAPMessage;
import com.sun.mail.imap.IMAPStore; import com.sun.mail.imap.IMAPStore;
import com.sun.mail.util.FolderClosedIOException; import com.sun.mail.util.FolderClosedIOException;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import javax.mail.FetchProfile; import javax.mail.FetchProfile;
@ -52,6 +54,8 @@ public class ViewModelBrowse extends ViewModel {
private String search; private String search;
private int pageSize; private int pageSize;
private int local = 0;
private List<Long> messages = null;
private IMAPStore istore = null; private IMAPStore istore = null;
private IMAPFolder ifolder = null; private IMAPFolder ifolder = null;
private Message[] imessages = null; private Message[] imessages = null;
@ -79,14 +83,61 @@ public class ViewModelBrowse extends ViewModel {
return context; return context;
} }
void load() throws MessagingException, FolderClosedIOException { void load() throws MessagingException, IOException {
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
EntityFolder folder = db.folder().getFolder(fid); EntityFolder folder = db.folder().getFolder(fid);
if (folder.account == null) // outbox
return; if (search != null)
EntityAccount account = db.account().getAccount(folder.account); try {
db.beginTransaction();
if (messages == null)
messages = db.message().getMessageByFolder(fid);
int matched = 0;
for (int i = local; i < messages.size() && matched < pageSize; i++) {
local = i + 1;
boolean match = false;
String find = search.toLowerCase();
EntityMessage message = db.message().getMessage(messages.get(i));
if (message.from != null)
for (int j = 0; j < message.from.length && !match; j++)
match = message.from[j].toString().toLowerCase().contains(find);
if (message.to != null)
for (int j = 0; j < message.to.length && !match; j++)
match = message.to[j].toString().toLowerCase().contains(find);
if (message.subject != null && !match)
match = message.subject.toLowerCase().contains(find);
if (!match && message.content)
match = message.read(context).toLowerCase().contains(find);
if (match) {
matched++;
message.id = null;
message.ui_found = true;
message.id = db.message().insertMessage(message);
}
}
db.setTransactionSuccessful();
if (++matched >= pageSize)
return;
} finally {
db.endTransaction();
}
if (imessages == null) { if (imessages == null) {
if (folder.account == null) // outbox
return;
EntityAccount account = db.account().getAccount(folder.account);
Properties props = MessageHelper.getSessionProperties(account.auth_type, account.insecure); Properties props = MessageHelper.getSessionProperties(account.auth_type, account.insecure);
props.setProperty("mail.imap.throwsearchexception", "true"); props.setProperty("mail.imap.throwsearchexception", "true");
Session isession = Session.getInstance(props, null); Session isession = Session.getInstance(props, null);
@ -179,6 +230,8 @@ public class ViewModelBrowse extends ViewModel {
Log.e(Helper.TAG, "Boundary " + ex + "\n" + Log.getStackTraceString(ex)); Log.e(Helper.TAG, "Boundary " + ex + "\n" + Log.getStackTraceString(ex));
} finally { } finally {
context = null; context = null;
local = 0;
messages = null;
istore = null; istore = null;
ifolder = null; ifolder = null;
imessages = null; imessages = null;

Loading…
Cancel
Save