mirror of
https://github.com/M66B/FairEmail.git
synced 2025-03-15 16:39:37 +00:00
Added auto classify setting
This commit is contained in:
parent
bf1d36ddfc
commit
34f1ae929b
8 changed files with 2387 additions and 13 deletions
2340
app/schemas/eu.faircode.email.DB/182.json
Normal file
2340
app/schemas/eu.faircode.email.DB/182.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -64,7 +64,7 @@ import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_PASSWORD;
|
||||||
// https://developer.android.com/topic/libraries/architecture/room.html
|
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
version = 181,
|
version = 182,
|
||||||
entities = {
|
entities = {
|
||||||
EntityIdentity.class,
|
EntityIdentity.class,
|
||||||
EntityAccount.class,
|
EntityAccount.class,
|
||||||
|
@ -1781,6 +1781,13 @@ public abstract class DB extends RoomDatabase {
|
||||||
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
||||||
db.execSQL("ALTER TABLE `rule` ADD COLUMN `last_applied` INTEGER");
|
db.execSQL("ALTER TABLE `rule` ADD COLUMN `last_applied` INTEGER");
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.addMigrations(new Migration(181, 182) {
|
||||||
|
@Override
|
||||||
|
public void migrate(@NonNull SupportSQLiteDatabase db) {
|
||||||
|
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
||||||
|
db.execSQL("ALTER TABLE `folder` ADD COLUMN `auto_classify` INTEGER NOT NULL DEFAULT 0");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,7 @@ public interface DaoFolder {
|
||||||
", unified = :unified" +
|
", unified = :unified" +
|
||||||
", navigation = :navigation" +
|
", navigation = :navigation" +
|
||||||
", notify = :notify" +
|
", notify = :notify" +
|
||||||
|
", auto_classify = :auto_classify" +
|
||||||
", hide = :hide" +
|
", hide = :hide" +
|
||||||
", synchronize = :synchronize" +
|
", synchronize = :synchronize" +
|
||||||
", poll = :poll" +
|
", poll = :poll" +
|
||||||
|
@ -293,7 +294,7 @@ public interface DaoFolder {
|
||||||
" WHERE id = :id")
|
" WHERE id = :id")
|
||||||
int setFolderProperties(
|
int setFolderProperties(
|
||||||
long id, String rename,
|
long id, String rename,
|
||||||
String display, Integer color, boolean unified, boolean navigation, boolean notify, boolean hide,
|
String display, Integer color, boolean unified, boolean navigation, boolean notify, boolean auto_classify, boolean hide,
|
||||||
boolean synchronize, boolean poll, int poll_factor, boolean download,
|
boolean synchronize, boolean poll, int poll_factor, boolean download,
|
||||||
int sync_days, int keep_days, boolean auto_delete);
|
int sync_days, int keep_days, boolean auto_delete);
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,8 @@ public class EntityFolder extends EntityOrder implements Serializable {
|
||||||
public Boolean navigation = false;
|
public Boolean navigation = false;
|
||||||
@NonNull
|
@NonNull
|
||||||
public Boolean notify = false;
|
public Boolean notify = false;
|
||||||
|
@NonNull
|
||||||
|
public Boolean auto_classify = false;
|
||||||
|
|
||||||
public Integer total; // messages on server
|
public Integer total; // messages on server
|
||||||
public String[] keywords;
|
public String[] keywords;
|
||||||
|
|
|
@ -64,6 +64,7 @@ public class FragmentFolder extends FragmentBase {
|
||||||
private CheckBox cbUnified;
|
private CheckBox cbUnified;
|
||||||
private CheckBox cbNavigation;
|
private CheckBox cbNavigation;
|
||||||
private CheckBox cbNotify;
|
private CheckBox cbNotify;
|
||||||
|
private CheckBox cbAutoClassify;
|
||||||
private CheckBox cbSynchronize;
|
private CheckBox cbSynchronize;
|
||||||
private CheckBox cbPoll;
|
private CheckBox cbPoll;
|
||||||
private EditText etPoll;
|
private EditText etPoll;
|
||||||
|
@ -124,6 +125,7 @@ public class FragmentFolder extends FragmentBase {
|
||||||
cbUnified = view.findViewById(R.id.cbUnified);
|
cbUnified = view.findViewById(R.id.cbUnified);
|
||||||
cbNavigation = view.findViewById(R.id.cbNavigation);
|
cbNavigation = view.findViewById(R.id.cbNavigation);
|
||||||
cbNotify = view.findViewById(R.id.cbNotify);
|
cbNotify = view.findViewById(R.id.cbNotify);
|
||||||
|
cbAutoClassify = view.findViewById(R.id.cbAutoClassify);
|
||||||
cbSynchronize = view.findViewById(R.id.cbSynchronize);
|
cbSynchronize = view.findViewById(R.id.cbSynchronize);
|
||||||
cbPoll = view.findViewById(R.id.cbPoll);
|
cbPoll = view.findViewById(R.id.cbPoll);
|
||||||
etPoll = view.findViewById(R.id.etPoll);
|
etPoll = view.findViewById(R.id.etPoll);
|
||||||
|
@ -158,6 +160,8 @@ public class FragmentFolder extends FragmentBase {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cbAutoClassify.setVisibility(MessageClassifier.isEnabled(getContext()) ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
cbSynchronize.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
cbSynchronize.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
@ -280,6 +284,7 @@ public class FragmentFolder extends FragmentBase {
|
||||||
cbUnified.setChecked(folder == null ? false : folder.unified);
|
cbUnified.setChecked(folder == null ? false : folder.unified);
|
||||||
cbNavigation.setChecked(folder == null ? false : folder.navigation);
|
cbNavigation.setChecked(folder == null ? false : folder.navigation);
|
||||||
cbNotify.setChecked(folder == null ? false : folder.notify);
|
cbNotify.setChecked(folder == null ? false : folder.notify);
|
||||||
|
cbAutoClassify.setChecked(folder == null ? false : folder.auto_classify);
|
||||||
cbSynchronize.setChecked(folder == null || folder.synchronize);
|
cbSynchronize.setChecked(folder == null || folder.synchronize);
|
||||||
cbPoll.setChecked(folder == null ? true : folder.poll);
|
cbPoll.setChecked(folder == null ? true : folder.poll);
|
||||||
etPoll.setText(folder == null ? null : Integer.toString(folder.poll_factor));
|
etPoll.setText(folder == null ? null : Integer.toString(folder.poll_factor));
|
||||||
|
@ -411,6 +416,7 @@ public class FragmentFolder extends FragmentBase {
|
||||||
args.putBoolean("unified", cbUnified.isChecked());
|
args.putBoolean("unified", cbUnified.isChecked());
|
||||||
args.putBoolean("navigation", cbNavigation.isChecked());
|
args.putBoolean("navigation", cbNavigation.isChecked());
|
||||||
args.putBoolean("notify", cbNotify.isChecked());
|
args.putBoolean("notify", cbNotify.isChecked());
|
||||||
|
args.putBoolean("auto_classify", cbAutoClassify.isChecked());
|
||||||
args.putBoolean("synchronize", cbSynchronize.isChecked());
|
args.putBoolean("synchronize", cbSynchronize.isChecked());
|
||||||
args.putBoolean("poll", cbPoll.isChecked());
|
args.putBoolean("poll", cbPoll.isChecked());
|
||||||
args.putString("factor", etPoll.getText().toString());
|
args.putString("factor", etPoll.getText().toString());
|
||||||
|
@ -453,6 +459,7 @@ public class FragmentFolder extends FragmentBase {
|
||||||
boolean unified = args.getBoolean("unified");
|
boolean unified = args.getBoolean("unified");
|
||||||
boolean navigation = args.getBoolean("navigation");
|
boolean navigation = args.getBoolean("navigation");
|
||||||
boolean notify = args.getBoolean("notify");
|
boolean notify = args.getBoolean("notify");
|
||||||
|
boolean auto_classify = args.getBoolean("auto_classify");
|
||||||
boolean synchronize = args.getBoolean("synchronize");
|
boolean synchronize = args.getBoolean("synchronize");
|
||||||
boolean poll = args.getBoolean("poll");
|
boolean poll = args.getBoolean("poll");
|
||||||
String factor = args.getString("factor");
|
String factor = args.getString("factor");
|
||||||
|
@ -506,6 +513,8 @@ public class FragmentFolder extends FragmentBase {
|
||||||
return true;
|
return true;
|
||||||
if (!Objects.equals(folder.notify, notify))
|
if (!Objects.equals(folder.notify, notify))
|
||||||
return true;
|
return true;
|
||||||
|
if (!Objects.equals(folder.auto_classify, auto_classify))
|
||||||
|
return true;
|
||||||
if (!Objects.equals(folder.hide, hide))
|
if (!Objects.equals(folder.hide, hide))
|
||||||
return true;
|
return true;
|
||||||
if (!Objects.equals(folder.synchronize, synchronize))
|
if (!Objects.equals(folder.synchronize, synchronize))
|
||||||
|
@ -555,6 +564,7 @@ public class FragmentFolder extends FragmentBase {
|
||||||
create.unified = unified;
|
create.unified = unified;
|
||||||
create.navigation = navigation;
|
create.navigation = navigation;
|
||||||
create.notify = notify;
|
create.notify = notify;
|
||||||
|
create.auto_classify = auto_classify;
|
||||||
create.hide = hide;
|
create.hide = hide;
|
||||||
create.synchronize = synchronize;
|
create.synchronize = synchronize;
|
||||||
create.poll = poll;
|
create.poll = poll;
|
||||||
|
@ -578,7 +588,7 @@ public class FragmentFolder extends FragmentBase {
|
||||||
Log.i("Updating folder=" + folder.name);
|
Log.i("Updating folder=" + folder.name);
|
||||||
db.folder().setFolderProperties(id,
|
db.folder().setFolderProperties(id,
|
||||||
folder.name.equals(name) ? null : name,
|
folder.name.equals(name) ? null : name,
|
||||||
display, color, unified, navigation, notify, hide,
|
display, color, unified, navigation, notify, auto_classify, hide,
|
||||||
synchronize, poll, poll_factor, download,
|
synchronize, poll, poll_factor, download,
|
||||||
sync_days, keep_days, auto_delete);
|
sync_days, keep_days, auto_delete);
|
||||||
db.folder().setFolderError(id, null);
|
db.folder().setFolderError(id, null);
|
||||||
|
|
|
@ -48,9 +48,9 @@ public class MessageClassifier {
|
||||||
private static final double COMMON_WORD_FACTOR = 0.75;
|
private static final double COMMON_WORD_FACTOR = 0.75;
|
||||||
private static final double CHANCE_THRESHOLD = 2.0;
|
private static final double CHANCE_THRESHOLD = 2.0;
|
||||||
|
|
||||||
static String classify(EntityMessage message, boolean added, Context context) {
|
static void classify(EntityMessage message, boolean added, Context context) {
|
||||||
if (!isEnabled(context))
|
if (!isEnabled(context))
|
||||||
return null;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
load(context);
|
load(context);
|
||||||
|
@ -62,21 +62,21 @@ public class MessageClassifier {
|
||||||
|
|
||||||
EntityFolder folder = db.folder().getFolder(message.folder);
|
EntityFolder folder = db.folder().getFolder(message.folder);
|
||||||
if (folder == null)
|
if (folder == null)
|
||||||
return null;
|
return;
|
||||||
|
|
||||||
EntityAccount account = db.account().getAccount(folder.account);
|
EntityAccount account = db.account().getAccount(folder.account);
|
||||||
if (account == null)
|
if (account == null)
|
||||||
return null;
|
return;
|
||||||
|
|
||||||
if (!EntityFolder.INBOX.equals(folder.type) &&
|
if (!EntityFolder.INBOX.equals(folder.type) &&
|
||||||
!EntityFolder.JUNK.equals(folder.type) &&
|
!EntityFolder.JUNK.equals(folder.type) &&
|
||||||
!EntityFolder.USER.equals(folder.type) &&
|
!EntityFolder.USER.equals(folder.type) &&
|
||||||
!(EntityFolder.ARCHIVE.equals(folder.type) && !account.isGmail()))
|
!(EntityFolder.ARCHIVE.equals(folder.type) && !account.isGmail()))
|
||||||
return null;
|
return;
|
||||||
|
|
||||||
File file = message.getFile(context);
|
File file = message.getFile(context);
|
||||||
if (!file.exists())
|
if (!file.exists())
|
||||||
return null;
|
return;
|
||||||
|
|
||||||
String text;
|
String text;
|
||||||
try {
|
try {
|
||||||
|
@ -87,7 +87,7 @@ public class MessageClassifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TextUtils.isEmpty(text))
|
if (TextUtils.isEmpty(text))
|
||||||
return null;
|
return;
|
||||||
|
|
||||||
if (!classMessages.containsKey(account.id))
|
if (!classMessages.containsKey(account.id))
|
||||||
classMessages.put(account.id, new HashMap<>());
|
classMessages.put(account.id, new HashMap<>());
|
||||||
|
@ -106,7 +106,11 @@ public class MessageClassifier {
|
||||||
}
|
}
|
||||||
Log.i("Classifier classify=" + folder.name + " messages=" + classMessages.get(account.id).get(folder.name));
|
Log.i("Classifier classify=" + folder.name + " messages=" + classMessages.get(account.id).get(folder.name));
|
||||||
|
|
||||||
return classified;
|
if (classified != null) {
|
||||||
|
EntityFolder f = db.folder().getFolderByName(account.id, classified);
|
||||||
|
if (f != null && f.auto_classify && !f.id.equals(folder.id))
|
||||||
|
EntityOperation.queue(context, message, EntityOperation.MOVE, f.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String classify(long account, String classify, String text, boolean added) {
|
private static String classify(long account, String classify, String text, boolean added) {
|
||||||
|
@ -295,7 +299,7 @@ public class MessageClassifier {
|
||||||
Log.i("Classifier loaded");
|
Log.i("Classifier loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isEnabled(Context context) {
|
static boolean isEnabled(Context context) {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
return prefs.getBoolean("classify", BuildConfig.DEBUG);
|
return prefs.getBoolean("classify", BuildConfig.DEBUG);
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,15 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cbNavigation" />
|
app:layout_constraintTop_toBottomOf="@id/cbNavigation" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/cbAutoClassify"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="@string/title_auto_classify"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/cbNotify" />
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/cbSynchronize"
|
android:id="@+id/cbSynchronize"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -143,7 +152,7 @@
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:text="@string/title_synchronize_folder"
|
android:text="@string/title_synchronize_folder"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cbNotify" />
|
app:layout_constraintTop_toBottomOf="@id/cbAutoClassify" />
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/cbPoll"
|
android:id="@+id/cbPoll"
|
||||||
|
|
|
@ -779,6 +779,7 @@
|
||||||
<string name="title_poll_folder">Check periodically instead of continuous synchronize</string>
|
<string name="title_poll_folder">Check periodically instead of continuous synchronize</string>
|
||||||
<string name="title_download_folder">Automatically download message texts and attachments</string>
|
<string name="title_download_folder">Automatically download message texts and attachments</string>
|
||||||
<string name="title_notify_folder">Notify on new messages</string>
|
<string name="title_notify_folder">Notify on new messages</string>
|
||||||
|
<string name="title_auto_classify" translatable="false">Automatically classify</string>
|
||||||
<string name="title_sync_days">Synchronize messages (days)</string>
|
<string name="title_sync_days">Synchronize messages (days)</string>
|
||||||
<string name="title_sync_days_remark">Increasing this value will increase battery and data usage</string>
|
<string name="title_sync_days_remark">Increasing this value will increase battery and data usage</string>
|
||||||
<string name="title_keep_days">Keep messages (days)</string>
|
<string name="title_keep_days">Keep messages (days)</string>
|
||||||
|
|
Loading…
Add table
Reference in a new issue