diff --git a/app/src/androidTest/java/net/mdln/englisc/TermHistoryTest.java b/app/src/androidTest/java/net/mdln/englisc/TermHistoryTest.java new file mode 100644 index 0000000..5ee194e --- /dev/null +++ b/app/src/androidTest/java/net/mdln/englisc/TermHistoryTest.java @@ -0,0 +1,31 @@ +package net.mdln.englisc; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + +public class TermHistoryTest { + + @Test + public void history() { + Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext(); + try (TermHistory history = new TermHistory(ctx, TermHistory.Location.IN_MEMORY, 0)) { + history.recordId(100, 1000); + history.recordId(101, 1001); + Set expectedIds = new HashSet(); + assertEquals(expectedIds, history.getIds(0)); + expectedIds.add(101); + assertEquals(expectedIds, history.getIds(1)); + expectedIds.add(100); + assertEquals(expectedIds, history.getIds(2)); + assertEquals(expectedIds, history.getIds(3)); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/net/mdln/englisc/TermHistory.java b/app/src/main/java/net/mdln/englisc/TermHistory.java new file mode 100644 index 0000000..23ed1f7 --- /dev/null +++ b/app/src/main/java/net/mdln/englisc/TermHistory.java @@ -0,0 +1,83 @@ +package net.mdln.englisc; + +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import androidx.annotation.Nullable; + +import java.io.File; +import java.util.HashSet; +import java.util.Set; + +/** + * Keeps track of term ids viewed and their timestamps so we can show recently viewed items + * in {@link MainActivity}. + */ +public class TermHistory implements AutoCloseable { + + private static final int SCHEMA_VERSION = 1; + + private final SQLiteOpenHelper databaseHelper; + + TermHistory(Context ctx, Location loc, long deleteHistoryBeforeMillis) { + this.databaseHelper = new OpenHelper(ctx, loc, deleteHistoryBeforeMillis / 1000.0); + } + + void recordId(int nid, long timeMillis) { + String sql = "INSERT INTO history (nid, timestamp_secs) VALUES (?, ?)"; + databaseHelper.getWritableDatabase().execSQL(sql, new Object[]{nid, timeMillis / 1000.0}); + } + + Set getIds(int limit) { + SQLiteDatabase db = databaseHelper.getReadableDatabase(); + Set ids = new HashSet<>(); + String sql = "SELECT nid FROM history ORDER BY timestamp_secs DESC LIMIT " + limit; + try (Cursor cursor = db.rawQuery(sql, new String[]{})) { + while (cursor.moveToNext()) { + ids.add(cursor.getInt(0)); + } + } + return ids; + } + + @Override + public void close() { + databaseHelper.close(); + } + + enum Location {ON_DISK, IN_MEMORY} + + private static final class OpenHelper extends SQLiteOpenHelper { + + private final double deleteHistoryBeforeSecs; + + public OpenHelper(Context context, Location loc, double deleteHistoryBeforeSecs) { + super(context, getPath(context, loc), null, SCHEMA_VERSION); + this.deleteHistoryBeforeSecs = deleteHistoryBeforeSecs; + } + + @Nullable + private static String getPath(Context context, Location loc) { + return loc == Location.IN_MEMORY ? null : + new File(context.getNoBackupFilesDir(), "history.db").toString(); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE history (nid INTEGER, timestamp_secs REAL)"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + } + + @Override + public void onOpen(SQLiteDatabase db) { + if (deleteHistoryBeforeSecs > 0) { + db.execSQL("DELETE FROM history WHERE timestamp_secs < ?", new String[]{String.valueOf(deleteHistoryBeforeSecs)}); + } + } + } +} diff --git a/app/src/main/java/net/mdln/englisc/WebViewStyle.java b/app/src/main/java/net/mdln/englisc/WebViewStyle.java index f285868..94ea261 100644 --- a/app/src/main/java/net/mdln/englisc/WebViewStyle.java +++ b/app/src/main/java/net/mdln/englisc/WebViewStyle.java @@ -30,7 +30,7 @@ public static void apply(Activity activity, WebView view, String html) { private static String styledHtml(Activity activity, String html, boolean night) { String headBlock = ""; String styleClass = night ? "dark" : "light"; - String bodyBlock = "" + html + ""; + String bodyBlock = "" + html + ""; return "" + headBlock + bodyBlock + ""; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e11a294..2a85b2d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -5,5 +5,5 @@ Close Feedback on %s TYPE FEEDBACK HERE - Type \'th\' for \'þ\' or \'ð\', and \'ae\' for \'æ\'. You can search for Anglo-Saxon words, Modern English words, and abbreviations. Got ideas for how to make the app better? Please let me know by selecting Feedback in the ⋮ menu. + Type \'th\' for \'þ\' or \'ð\', and \'ae\' for \'æ\'. You can search for Anglo-Saxon and Modern English words.