Advanced folder type guessing

pull/178/head
M66B 5 years ago
parent b6f4525e0c
commit 45440fcd50

@ -585,7 +585,6 @@ public class EmailService implements AutoCloseable {
List<EntityFolder> getFolders() throws MessagingException { List<EntityFolder> getFolders() throws MessagingException {
List<EntityFolder> folders = new ArrayList<>(); List<EntityFolder> folders = new ArrayList<>();
List<EntityFolder> guesses = new ArrayList<>();
for (Folder ifolder : getStore().getDefaultFolder().list("*")) { for (Folder ifolder : getStore().getDefaultFolder().list("*")) {
String fullName = ifolder.getFullName(); String fullName = ifolder.getFullName();
@ -593,32 +592,11 @@ public class EmailService implements AutoCloseable {
String type = EntityFolder.getType(attrs, fullName, true); String type = EntityFolder.getType(attrs, fullName, true);
Log.i(fullName + " attrs=" + TextUtils.join(" ", attrs) + " type=" + type); Log.i(fullName + " attrs=" + TextUtils.join(" ", attrs) + " type=" + type);
if (type != null) { if (type != null)
EntityFolder folder = new EntityFolder(fullName, type); folders.add(new EntityFolder(fullName, type));
folders.add(folder);
if (EntityFolder.USER.equals(type)) {
String guess = EntityFolder.guessType(fullName);
if (guess != null)
guesses.add(folder);
}
}
} }
for (EntityFolder guess : guesses) { EntityFolder.guessTypes(folders, getStore().getDefaultFolder().getSeparator());
boolean has = false;
String gtype = EntityFolder.guessType(guess.name);
for (EntityFolder folder : folders)
if (folder.type.equals(gtype)) {
has = true;
break;
}
if (!has) {
guess.type = gtype;
guess.setProperties();
Log.i(guess.name + " guessed type=" + gtype);
}
}
boolean inbox = false; boolean inbox = false;
boolean drafts = false; boolean drafts = false;

@ -20,6 +20,7 @@ package eu.faircode.email;
*/ */
import android.content.Context; import android.content.Context;
import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.room.Entity; import androidx.room.Entity;
@ -33,6 +34,7 @@ import org.json.JSONObject;
import java.io.Serializable; import java.io.Serializable;
import java.text.Collator; import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -167,20 +169,21 @@ public class EntityFolder extends EntityOrder implements Serializable {
ARCHIVE ARCHIVE
)); ));
private static Map<String, String> GUESS_FOLDER_TYPE = new HashMap<String, String>() {{ private static Map<String, TypeScore> GUESS_FOLDER_TYPE = new HashMap<String, TypeScore>() {{
// Contains: // Contains:
put("all", EntityFolder.ARCHIVE); put("all", new TypeScore(EntityFolder.ARCHIVE, 100));
put("archive", EntityFolder.ARCHIVE); put("archive", new TypeScore(EntityFolder.ARCHIVE, 100));
put("draft", EntityFolder.DRAFTS); put("draft", new TypeScore(EntityFolder.DRAFTS, 100));
put("concept", EntityFolder.DRAFTS); put("concept", new TypeScore(EntityFolder.DRAFTS, 100));
put("brouillon", EntityFolder.DRAFTS); put("brouillon", new TypeScore(EntityFolder.DRAFTS, 100));
put("trash", EntityFolder.TRASH); put("trash", new TypeScore(EntityFolder.TRASH, 100));
put("corbeille", EntityFolder.TRASH); put("corbeille", new TypeScore(EntityFolder.TRASH, 100));
put("junk", EntityFolder.JUNK); put("junk", new TypeScore(EntityFolder.JUNK, 100));
put("spam", EntityFolder.JUNK); put("spam", new TypeScore(EntityFolder.JUNK, 100));
put("pourriel", EntityFolder.JUNK); put("pourriel", new TypeScore(EntityFolder.JUNK, 100));
put("sent", EntityFolder.SENT); put("quarantaine", new TypeScore(EntityFolder.JUNK, 50));
put("envoyé", EntityFolder.SENT); put("sent", new TypeScore(EntityFolder.SENT, 100));
put("envoyé", new TypeScore(EntityFolder.SENT, 100));
}}; }};
static final int DEFAULT_SYNC = 7; // days static final int DEFAULT_SYNC = 7; // days
@ -327,11 +330,73 @@ public class EntityFolder extends EntityOrder implements Serializable {
return USER; return USER;
} }
static String guessType(String fullName) { private static class TypeScore {
String type;
int score;
TypeScore(String type, int score) {
this.score = score;
this.type = type;
}
}
private static class FolderScore {
EntityFolder folder;
int score;
FolderScore(EntityFolder folder, int score) {
this.score = score;
this.folder = folder;
}
@NonNull
@Override
public String toString() {
return folder.name + ":" + score;
}
}
static void guessTypes(List<EntityFolder> folders, final char separator) {
List<String> types = new ArrayList<>();
Map<String, List<FolderScore>> typeFolderScore = new HashMap<>();
for (EntityFolder folder : folders)
if (EntityFolder.USER.equals(folder.type) || BuildConfig.DEBUG) {
for (String guess : GUESS_FOLDER_TYPE.keySet()) for (String guess : GUESS_FOLDER_TYPE.keySet())
if (fullName.toLowerCase(Locale.ROOT).contains(guess)) if (folder.name.toLowerCase(Locale.ROOT).contains(guess)) {
return GUESS_FOLDER_TYPE.get(guess); TypeScore score = GUESS_FOLDER_TYPE.get(guess);
return null; if (!typeFolderScore.containsKey(score.type))
typeFolderScore.put(score.type, new ArrayList<>());
typeFolderScore.get(score.type).add(new FolderScore(folder, score.score));
break;
}
} else
types.add(folder.type);
for (String type : typeFolderScore.keySet()) {
List<FolderScore> candidates = typeFolderScore.get(type);
Log.i("Guess type=" + type + " candidates=" + TextUtils.join(", ", candidates));
if (!types.contains(type)) {
Collections.sort(candidates, new Comparator<FolderScore>() {
@Override
public int compare(FolderScore fs1, FolderScore fs2) {
int s = Integer.compare(fs1.score, fs2.score);
if (s == 0) {
String sep = String.valueOf(separator);
return Integer.compare(
fs1.folder.name.split(sep).length,
fs2.folder.name.split(sep).length);
} else
return s;
}
});
candidates.get(0).folder.type = type;
candidates.get(0).folder.setProperties();
Log.i(candidates.get(0).folder.name + " guessed type=" + type);
types.add(type);
}
}
} }
String getParentName(Character separator) { String getParentName(Character separator) {

@ -24,7 +24,6 @@ import android.accounts.AccountManager;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.net.Uri; import android.net.Uri;
@ -59,7 +58,6 @@ import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.Group; import androidx.constraintlayout.widget.Group;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import androidx.preference.PreferenceManager;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
@ -653,8 +651,6 @@ public class FragmentAccount extends FragmentBase {
if (TextUtils.isEmpty(realm)) if (TextUtils.isEmpty(realm))
realm = null; realm = null;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
CheckResult result = new CheckResult(); CheckResult result = new CheckResult();
@ -674,9 +670,6 @@ public class FragmentAccount extends FragmentBase {
result.idle = iservice.hasCapability("IDLE"); result.idle = iservice.hasCapability("IDLE");
boolean inbox = false; boolean inbox = false;
List<EntityFolder> guesses = new ArrayList<>();
for (Folder ifolder : iservice.getStore().getDefaultFolder().list("*")) { for (Folder ifolder : iservice.getStore().getDefaultFolder().list("*")) {
// Check folder attributes // Check folder attributes
String fullName = ifolder.getFullName(); String fullName = ifolder.getFullName();
@ -697,12 +690,6 @@ public class FragmentAccount extends FragmentBase {
folder = new EntityFolder(fullName, type); folder = new EntityFolder(fullName, type);
result.folders.add(folder); result.folders.add(folder);
if (EntityFolder.USER.equals(type)) {
String guess = EntityFolder.guessType(fullName);
if (guess != null)
guesses.add(folder);
}
if (EntityFolder.INBOX.equals(type)) { if (EntityFolder.INBOX.equals(type)) {
inbox = true; inbox = true;
@ -719,20 +706,7 @@ public class FragmentAccount extends FragmentBase {
} }
} }
for (EntityFolder guess : guesses) { EntityFolder.guessTypes(result.folders, iservice.getStore().getDefaultFolder().getSeparator());
boolean has = false;
String gtype = EntityFolder.guessType(guess.name);
for (EntityFolder folder : result.folders)
if (folder.type.equals(gtype)) {
has = true;
break;
}
if (!has) {
guess.type = gtype;
guess.setProperties();
Log.i(guess.name + " guessed type=" + gtype);
}
}
if (!inbox) if (!inbox)
throw new IllegalArgumentException(context.getString(R.string.title_no_inbox)); throw new IllegalArgumentException(context.getString(R.string.title_no_inbox));

Loading…
Cancel
Save