From 45440fcd50e8d1e5d10674abf3438f36dcccff1e Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 7 May 2020 09:31:32 +0200 Subject: [PATCH] Advanced folder type guessing --- .../java/eu/faircode/email/EmailService.java | 28 +---- .../java/eu/faircode/email/EntityFolder.java | 101 ++++++++++++++---- .../eu/faircode/email/FragmentAccount.java | 28 +---- 3 files changed, 87 insertions(+), 70 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/EmailService.java b/app/src/main/java/eu/faircode/email/EmailService.java index fd5f157224..b5352224dd 100644 --- a/app/src/main/java/eu/faircode/email/EmailService.java +++ b/app/src/main/java/eu/faircode/email/EmailService.java @@ -585,7 +585,6 @@ public class EmailService implements AutoCloseable { List getFolders() throws MessagingException { List folders = new ArrayList<>(); - List guesses = new ArrayList<>(); for (Folder ifolder : getStore().getDefaultFolder().list("*")) { String fullName = ifolder.getFullName(); @@ -593,32 +592,11 @@ public class EmailService implements AutoCloseable { String type = EntityFolder.getType(attrs, fullName, true); Log.i(fullName + " attrs=" + TextUtils.join(" ", attrs) + " type=" + type); - if (type != null) { - EntityFolder folder = new EntityFolder(fullName, type); - folders.add(folder); - - if (EntityFolder.USER.equals(type)) { - String guess = EntityFolder.guessType(fullName); - if (guess != null) - guesses.add(folder); - } - } + if (type != null) + folders.add(new EntityFolder(fullName, type)); } - for (EntityFolder guess : guesses) { - 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); - } - } + EntityFolder.guessTypes(folders, getStore().getDefaultFolder().getSeparator()); boolean inbox = false; boolean drafts = false; diff --git a/app/src/main/java/eu/faircode/email/EntityFolder.java b/app/src/main/java/eu/faircode/email/EntityFolder.java index 063093d41f..2771f2cf0c 100644 --- a/app/src/main/java/eu/faircode/email/EntityFolder.java +++ b/app/src/main/java/eu/faircode/email/EntityFolder.java @@ -20,6 +20,7 @@ package eu.faircode.email; */ import android.content.Context; +import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.room.Entity; @@ -33,6 +34,7 @@ import org.json.JSONObject; import java.io.Serializable; import java.text.Collator; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; @@ -167,20 +169,21 @@ public class EntityFolder extends EntityOrder implements Serializable { ARCHIVE )); - private static Map GUESS_FOLDER_TYPE = new HashMap() {{ + private static Map GUESS_FOLDER_TYPE = new HashMap() {{ // Contains: - put("all", EntityFolder.ARCHIVE); - put("archive", EntityFolder.ARCHIVE); - put("draft", EntityFolder.DRAFTS); - put("concept", EntityFolder.DRAFTS); - put("brouillon", EntityFolder.DRAFTS); - put("trash", EntityFolder.TRASH); - put("corbeille", EntityFolder.TRASH); - put("junk", EntityFolder.JUNK); - put("spam", EntityFolder.JUNK); - put("pourriel", EntityFolder.JUNK); - put("sent", EntityFolder.SENT); - put("envoyé", EntityFolder.SENT); + put("all", new TypeScore(EntityFolder.ARCHIVE, 100)); + put("archive", new TypeScore(EntityFolder.ARCHIVE, 100)); + put("draft", new TypeScore(EntityFolder.DRAFTS, 100)); + put("concept", new TypeScore(EntityFolder.DRAFTS, 100)); + put("brouillon", new TypeScore(EntityFolder.DRAFTS, 100)); + put("trash", new TypeScore(EntityFolder.TRASH, 100)); + put("corbeille", new TypeScore(EntityFolder.TRASH, 100)); + put("junk", new TypeScore(EntityFolder.JUNK, 100)); + put("spam", new TypeScore(EntityFolder.JUNK, 100)); + put("pourriel", new TypeScore(EntityFolder.JUNK, 100)); + put("quarantaine", new TypeScore(EntityFolder.JUNK, 50)); + put("sent", new TypeScore(EntityFolder.SENT, 100)); + put("envoyé", new TypeScore(EntityFolder.SENT, 100)); }}; static final int DEFAULT_SYNC = 7; // days @@ -327,11 +330,73 @@ public class EntityFolder extends EntityOrder implements Serializable { return USER; } - static String guessType(String fullName) { - for (String guess : GUESS_FOLDER_TYPE.keySet()) - if (fullName.toLowerCase(Locale.ROOT).contains(guess)) - return GUESS_FOLDER_TYPE.get(guess); - return null; + 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 folders, final char separator) { + List types = new ArrayList<>(); + Map> typeFolderScore = new HashMap<>(); + + for (EntityFolder folder : folders) + if (EntityFolder.USER.equals(folder.type) || BuildConfig.DEBUG) { + for (String guess : GUESS_FOLDER_TYPE.keySet()) + if (folder.name.toLowerCase(Locale.ROOT).contains(guess)) { + TypeScore score = GUESS_FOLDER_TYPE.get(guess); + 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 candidates = typeFolderScore.get(type); + Log.i("Guess type=" + type + " candidates=" + TextUtils.join(", ", candidates)); + if (!types.contains(type)) { + Collections.sort(candidates, new Comparator() { + @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) { diff --git a/app/src/main/java/eu/faircode/email/FragmentAccount.java b/app/src/main/java/eu/faircode/email/FragmentAccount.java index 5ad6cb2edb..93b5b8629f 100644 --- a/app/src/main/java/eu/faircode/email/FragmentAccount.java +++ b/app/src/main/java/eu/faircode/email/FragmentAccount.java @@ -24,7 +24,6 @@ import android.accounts.AccountManager; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.Paint; import android.net.Uri; @@ -59,7 +58,6 @@ import androidx.annotation.Nullable; import androidx.constraintlayout.widget.Group; import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.Lifecycle; -import androidx.preference.PreferenceManager; import com.google.android.material.snackbar.Snackbar; import com.google.android.material.textfield.TextInputLayout; @@ -653,8 +651,6 @@ public class FragmentAccount extends FragmentBase { if (TextUtils.isEmpty(realm)) realm = null; - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - DB db = DB.getInstance(context); CheckResult result = new CheckResult(); @@ -674,9 +670,6 @@ public class FragmentAccount extends FragmentBase { result.idle = iservice.hasCapability("IDLE"); boolean inbox = false; - - List guesses = new ArrayList<>(); - for (Folder ifolder : iservice.getStore().getDefaultFolder().list("*")) { // Check folder attributes String fullName = ifolder.getFullName(); @@ -697,12 +690,6 @@ public class FragmentAccount extends FragmentBase { folder = new EntityFolder(fullName, type); 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)) { inbox = true; @@ -719,20 +706,7 @@ public class FragmentAccount extends FragmentBase { } } - for (EntityFolder guess : guesses) { - 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); - } - } + EntityFolder.guessTypes(result.folders, iservice.getStore().getDefaultFolder().getSeparator()); if (!inbox) throw new IllegalArgumentException(context.getString(R.string.title_no_inbox));