Link log entries to accounts, folders and messages

pull/204/head
M66B 3 years ago
parent 4c6c72afd9
commit 0b3b3e6d2a

File diff suppressed because it is too large Load Diff

@ -51,7 +51,10 @@ public class AdapterLog extends RecyclerView.Adapter<AdapterLog.ViewHolder> {
private int colorAccent;
private int colorWarning;
List<EntityLog.Type> types = new ArrayList<>();
private Long account = null;
private Long folder = null;
private Long message = null;
private List<EntityLog.Type> types = new ArrayList<>();
private List<EntityLog> all = new ArrayList<>();
private List<EntityLog> selected = new ArrayList<>();
@ -120,16 +123,28 @@ public class AdapterLog extends RecyclerView.Adapter<AdapterLog.ViewHolder> {
});
}
public void set(@NonNull List<EntityLog> logs, @NonNull List<EntityLog.Type> types) {
public void set(@NonNull List<EntityLog> logs,
Long account, Long folder, Long message,
@NonNull List<EntityLog.Type> types) {
Log.i("Set logs=" + logs.size());
this.all = logs;
this.account = account;
this.folder = folder;
this.message = message;
this.types = types;
List<EntityLog> items = new ArrayList<>();
for (EntityLog log : all)
if (types.contains(log.type))
items.add(log);
if (account == null && folder == null && message == null) {
if (types.contains(log.type))
items.add(log);
} else {
if ((account == null || account.equals(log.account)) &&
(folder == null || folder.equals(log.folder)) &&
(message == null || message.equals(log.message)))
items.add(log);
}
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(selected, items), false);
@ -160,7 +175,7 @@ public class AdapterLog extends RecyclerView.Adapter<AdapterLog.ViewHolder> {
}
public void setTypes(@NonNull List<EntityLog.Type> types) {
set(all, types);
set(all, account, folder, message, types);
}
private static class DiffCallback extends DiffUtil.Callback {

@ -124,6 +124,8 @@ import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
@ -4646,6 +4648,9 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
} else if (itemId == R.id.menu_raw_send_thread) {
onMenuRawSend(message, true);
return true;
} else if (itemId == R.id.menu_log) {
onMenuLog(message);
return true;
}
return false;
}
@ -5352,6 +5357,21 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
}.execute(context, owner, args, "message:raw");
}
private void onMenuLog(TupleMessageEx message) {
if (owner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
parentFragment.getParentFragmentManager().popBackStack("logs", FragmentManager.POP_BACK_STACK_INCLUSIVE);
Bundle args = new Bundle();
args.putLong("message", message.id);
Fragment fragment = new FragmentLogs();
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = parentFragment.getParentFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("logs");
fragmentTransaction.commit();
}
private SpannableStringBuilder getKeywords(TupleMessageEx message) {
SpannableStringBuilder ssb = new SpannableStringBuilder();

@ -67,7 +67,7 @@ import io.requery.android.database.sqlite.SQLiteDatabase;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 208,
version = 209,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -2106,6 +2106,14 @@ public abstract class DB extends RoomDatabase {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `log` ADD COLUMN `type` INTEGER NOT NULL DEFAULT " + EntityLog.Type.General.ordinal());
}
}).addMigrations(new Migration(208, 209) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `log` ADD COLUMN `account` INTEGER");
db.execSQL("ALTER TABLE `log` ADD COLUMN `folder` INTEGER");
db.execSQL("ALTER TABLE `log` ADD COLUMN `message` INTEGER");
}
}).addMigrations(new Migration(998, 999) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {

@ -56,6 +56,9 @@ public class EntityLog {
public Long time;
@NonNull
public Type type = Type.General;
public Long account;
public Long folder;
public Long message;
@NonNull
public String data;
@ -68,7 +71,27 @@ public class EntityLog {
log(context, Type.General, data);
}
static void log(final Context context, Type type, EntityAccount account, String data) {
log(context, type, account.id, null, null, account.name + " " + data);
}
static void log(final Context context, Type type, EntityAccount account, EntityFolder folder, String data) {
log(context, type, account.id, folder.id, null, account.name + "/" + folder.name + " " + data);
}
static void log(final Context context, Type type, EntityFolder folder, String data) {
log(context, type, folder.account, folder.id, null, folder.name + " " + data);
}
static void log(final Context context, Type type, EntityMessage message, String data) {
log(context, type, message.account, message.folder, message.id, data);
}
static void log(final Context context, Type type, String data) {
log(context, type, null, null, null, data);
}
static void log(final Context context, Type type, Long account, Long folder, Long message, String data) {
Log.i(data);
if (context == null)
@ -82,6 +105,9 @@ public class EntityLog {
final EntityLog entry = new EntityLog();
entry.time = new Date().getTime();
entry.type = type;
entry.account = account;
entry.folder = folder;
entry.message = message;
entry.data = data;
final DB db = DB.getInstance(context);

@ -47,6 +47,9 @@ public class FragmentLogs extends FragmentBase {
private ContentLoadingProgressBar pbWait;
private Group grpReady;
private Long account = null;
private Long folder = null;
private Long message = null;
private boolean autoScroll = true;
private AdapterLog adapter;
@ -54,6 +57,22 @@ public class FragmentLogs extends FragmentBase {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args == null)
args = new Bundle();
account = args.getLong("account", -1L);
folder = args.getLong("folder", -1L);
message = args.getLong("message", -1L);
if (account < 0)
account = null;
if (folder < 0)
folder = null;
if (message < 0)
message = null;
if (savedInstanceState != null)
autoScroll = savedInstanceState.getBoolean("fair:scroll");
}
@ -100,7 +119,7 @@ public class FragmentLogs extends FragmentBase {
if (logs == null)
logs = new ArrayList<>();
adapter.set(logs, getTypes());
adapter.set(logs, account, folder, message, getTypes());
if (autoScroll)
rvLog.scrollToPosition(0);
@ -127,8 +146,12 @@ public class FragmentLogs extends FragmentBase {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
boolean main_log = prefs.getBoolean("main_log", true);
boolean all = (account == null && folder == null && message == null);
menu.findItem(R.id.menu_enabled).setChecked(main_log);
menu.findItem(R.id.menu_auto_scroll).setChecked(autoScroll);
menu.findItem(R.id.menu_show).setVisible(all);
menu.findItem(R.id.menu_clear).setVisible(all);
List<EntityLog.Type> types = getTypes();
SubMenu smenu = menu.findItem(R.id.menu_show).getSubMenu();

@ -87,10 +87,10 @@ public class MessageClassifier {
wordClassFrequency.put(folder.account, new HashMap<>());
// Classify texts
String classified = classify(folder.account, folder.name, texts, target == null, context);
String classified = classify(message, folder.name, texts, target == null, context);
long elapsed = new Date().getTime() - start;
EntityLog.log(context, EntityLog.Type.Classification,
EntityLog.log(context, EntityLog.Type.Classification, message,
"Classifier" +
" folder=" + folder.name +
" message=" + message.id +
@ -175,26 +175,26 @@ public class MessageClassifier {
return texts;
}
private static String classify(long account, @NonNull String currentClass, @NonNull List<String> texts, boolean added, @NonNull Context context) {
private static String classify(EntityMessage message, @NonNull String currentClass, @NonNull List<String> texts, boolean added, @NonNull Context context) {
State state = new State();
// Check classes
DB db = DB.getInstance(context);
for (String clazz : new ArrayList<>(classMessages.get(account).keySet())) {
EntityFolder folder = db.folder().getFolderByName(account, clazz);
for (String clazz : new ArrayList<>(classMessages.get(message.account).keySet())) {
EntityFolder folder = db.folder().getFolderByName(message.account, clazz);
if (folder == null) {
EntityLog.log(context, EntityLog.Type.Classification,
"Classifier deleting folder class=" + account + ":" + clazz);
classMessages.get(account).remove(clazz);
for (String word : wordClassFrequency.get(account).keySet())
wordClassFrequency.get(account).get(word).remove(clazz);
EntityLog.log(context, EntityLog.Type.Classification, message,
"Classifier deleting folder class=" + message.account + ":" + clazz);
classMessages.get(message.account).remove(clazz);
for (String word : wordClassFrequency.get(message.account).keySet())
wordClassFrequency.get(message.account).get(word).remove(clazz);
}
}
Log.i("Classifier texts=" + texts.size());
for (String text : texts) {
// First word
processWord(account, added, null, state);
processWord(message.account, added, null, state);
// Process words
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
@ -203,7 +203,7 @@ public class MessageClassifier {
int start = boundary.first();
for (int end = boundary.next(); end != java.text.BreakIterator.DONE; end = boundary.next()) {
String word = text.substring(start, end);
processWord(account, added, word, state);
processWord(message.account, added, word, state);
if (state.words.size() >= MAX_WORDS)
break;
start = end;
@ -215,7 +215,7 @@ public class MessageClassifier {
int start = boundary.first();
for (int end = boundary.next(); end != android.icu.text.BreakIterator.DONE; end = boundary.next()) {
String word = text.substring(start, end);
processWord(account, added, word, state);
processWord(message.account, added, word, state);
if (state.words.size() >= MAX_WORDS)
break;
start = end;
@ -224,19 +224,19 @@ public class MessageClassifier {
}
// final word
processWord(account, added, null, state);
processWord(message.account, added, null, state);
int maxMessages = 0;
for (String clazz : classMessages.get(account).keySet()) {
int count = classMessages.get(account).get(clazz);
for (String clazz : classMessages.get(message.account).keySet()) {
int count = classMessages.get(message.account).get(clazz);
if (count > maxMessages)
maxMessages = count;
}
updateFrequencies(account, currentClass, added, state);
updateFrequencies(message.account, currentClass, added, state);
if (maxMessages == 0) {
Log.i("Classifier no messages account=" + account);
Log.i("Classifier no messages account=" + message.account);
return null;
}
@ -252,7 +252,7 @@ public class MessageClassifier {
double chance = stat.totalFrequency / maxMessages / words;
Chance c = new Chance(clazz, chance);
chances.add(c);
EntityLog.log(context, EntityLog.Type.Classification,
EntityLog.log(context, EntityLog.Type.Classification, message,
"Classifier " + c +
" frequency=" + (Math.round(stat.totalFrequency * 100.0) / 100.0) + "/" + maxMessages + " msgs" +
" matched=" + stat.matchedWords + "/" + words + " words" +

@ -136,4 +136,9 @@
android:title="@string/title_raw_send_thread" />
</menu>
</item>
<item
android:id="@+id/menu_log"
android:icon="@drawable/twotone_dns_24"
android:title="@string/title_log" />
</menu>

Loading…
Cancel
Save