From e4d94af86cac400c0b8468f54ca2e8ee5f2888c6 Mon Sep 17 00:00:00 2001 From: TBog Date: Wed, 14 Dec 2022 15:37:36 +0200 Subject: [PATCH] update Dock after sort order changed --- .../tblauncher/dataprovider/TagsProvider.java | 12 +-- .../rocks/tbog/tblauncher/db/DBHelper.java | 25 +++++- .../rocks/tbog/tblauncher/entry/TagEntry.java | 56 +++++++++++--- .../tbog/tblauncher/entry/TagSortEntry.java | 65 +++++++--------- .../tbog/tblauncher/handler/DataHandler.java | 34 ++++++++- .../tbog/tblauncher/handler/TagsHandler.java | 76 ++++++++++++++----- .../tblauncher/searcher/HistorySearcher.java | 1 + .../tbog/tblauncher/searcher/Searcher.java | 25 ++++-- .../searcher/SortedTagSearcher.java | 49 ++++++++---- .../tbog/tblauncher/searcher/TagList.java | 5 +- .../tbog/tblauncher/searcher/TagSearcher.java | 3 +- 11 files changed, 246 insertions(+), 105 deletions(-) diff --git a/app/src/main/java/rocks/tbog/tblauncher/dataprovider/TagsProvider.java b/app/src/main/java/rocks/tbog/tblauncher/dataprovider/TagsProvider.java index 78e27a2a..2a6a6b3a 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/dataprovider/TagsProvider.java +++ b/app/src/main/java/rocks/tbog/tblauncher/dataprovider/TagsProvider.java @@ -9,8 +9,8 @@ import java.util.List; import rocks.tbog.tblauncher.db.ModRecord; -import rocks.tbog.tblauncher.entry.TagSortEntry; import rocks.tbog.tblauncher.entry.TagEntry; +import rocks.tbog.tblauncher.entry.TagSortEntry; import rocks.tbog.tblauncher.handler.DataHandler; public class TagsProvider extends DBProvider { @@ -32,9 +32,7 @@ public static TagEntry newTagEntryCheckId(String id) { tagEntry = new TagSortEntry(id); // set default name (based on id) tagEntry.setName(null); - } - // now check if it's a tag - if (id.startsWith(TagEntry.SCHEME)) { + } else if (id.startsWith(TagEntry.SCHEME)) { tagEntry = new TagEntry(id); String tagName = id.substring(TagEntry.SCHEME.length()); tagEntry.setName(tagName); @@ -49,7 +47,11 @@ public static String getTagId(@NonNull String tagName) { @NonNull private static TagEntry newTagEntry(@NonNull String id, @NonNull String tagName) { - TagEntry tagEntry = new TagEntry(id); + TagEntry tagEntry; + if (TagSortEntry.isTagSort(id)) + tagEntry = new TagSortEntry(id); + else + tagEntry = new TagEntry(id); tagEntry.setName(tagName); return tagEntry; } diff --git a/app/src/main/java/rocks/tbog/tblauncher/db/DBHelper.java b/app/src/main/java/rocks/tbog/tblauncher/db/DBHelper.java index 30d4cdb1..d126c57a 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/db/DBHelper.java +++ b/app/src/main/java/rocks/tbog/tblauncher/db/DBHelper.java @@ -134,8 +134,7 @@ private static Cursor getHistoryByFrecency(SQLiteDatabase db, int limit) { " GROUP BY record " + " ORDER BY " + " count(*) * 1.0 / (select count(*) from history LIMIT " + historyWindowSize + ") / ((SELECT _id FROM history ORDER BY _id DESC LIMIT 1) - max(_id) + 0.001) " + - " DESC " + - " LIMIT " + limit; + " DESC " + ((limit > 0 && limit < Integer.MAX_VALUE) ? (" LIMIT " + limit) : ""); return db.rawQuery(sql, null); } @@ -144,7 +143,7 @@ private static Cursor getHistoryByFrequency(SQLiteDatabase db, int limit) { String sql = "SELECT record, count(*) FROM history" + " GROUP BY record " + " ORDER BY count(*) DESC " + - " LIMIT " + limit; + ((limit > 0 && limit < Integer.MAX_VALUE) ? (" LIMIT " + limit) : ""); return db.rawQuery(sql, null); } @@ -168,7 +167,7 @@ private static Cursor getHistoryByAdaptive(SQLiteDatabase db, int hours, int lim "AND timeStamp >" + (System.currentTimeMillis() - (hours * 3600000)) + " GROUP BY record " + " ORDER BY count(*) DESC " + - " LIMIT " + limit; + ((limit > 0 && limit < Integer.MAX_VALUE) ? (" LIMIT " + limit) : ""); return db.rawQuery(sql, null); } @@ -490,6 +489,24 @@ public static int renameTag(Context context, String tagName, String newName, @Nu return db.update("tags", values, "tag = ?", new String[]{tagName}); } + /** + * @param context android context + * @param tagEntry what tag to modify + * @param newEntry the new tag sort + * @return number of records affected + */ + public static int changeTagSort(Context context, @NonNull TagEntry tagEntry, @NonNull TagEntry newEntry) { + SQLiteDatabase db = getDatabase(context); + + ContentValues values = new ContentValues(); + values.put("record", newEntry.id); + int count = db.updateWithOnConflict("favorites", values, "record = ?", new String[]{tagEntry.id}, SQLiteDatabase.CONFLICT_REPLACE); + if (count != 1) { + Log.e(TAG, "Update favorites in rename tag; count = " + count); + } + return count; + } + /** * @param context android context * @return HashMap with EntryItem id as key and an ArrayList of tags for each diff --git a/app/src/main/java/rocks/tbog/tblauncher/entry/TagEntry.java b/app/src/main/java/rocks/tbog/tblauncher/entry/TagEntry.java index a21b4559..e38a4eab 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/entry/TagEntry.java +++ b/app/src/main/java/rocks/tbog/tblauncher/entry/TagEntry.java @@ -20,8 +20,11 @@ public class TagEntry extends StaticEntry { public TagEntry(@NonNull String id) { super(id, 0); - if (BuildConfig.DEBUG && !id.startsWith(SCHEME)) { - throw new IllegalStateException("Invalid " + TagEntry.class.getSimpleName() + " id `" + id + "`"); + if (BuildConfig.DEBUG) { + if (!id.startsWith(SCHEME)) + throw new IllegalStateException("Invalid " + TagEntry.class.getSimpleName() + " id `" + id + "`"); + if (!(this instanceof TagSortEntry) && TagSortEntry.isTagSort(id)) + throw new IllegalStateException(TagEntry.class.getSimpleName() + " instantiated with id `" + id + "`"); } } @@ -36,11 +39,42 @@ public void setName(String name) { } } + @Override + protected void buildPopupMenuCategory(Context context, @NonNull LinearAdapter adapter, int titleStringId) { + if (titleStringId == R.string.popup_title_hist_fav) { + adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_az)); + adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_za)); + adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_hist_rec)); + adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_hist_freq)); + adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_hist_frec)); + adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_hist_adaptive)); + } + super.buildPopupMenuCategory(context, adapter, titleStringId); + } + @Override boolean popupMenuClickHandler(@NonNull View view, @NonNull LinearAdapter.MenuItem item, int stringId, View parentView) { + Context ctx = view.getContext(); + boolean changesMade = false; if (stringId == R.string.menu_action_rename) { - Context ctx = view.getContext(); launchRenameDialog(ctx); + changesMade = true; + } else if (stringId == R.string.menu_tag_sort_az) { + changesMade = TBApplication.tagsHandler(ctx).changeTagSort(id, SCHEME + TagSortEntry.SORT_AZ + getName()); + } else if (stringId == R.string.menu_tag_sort_za) { + changesMade = TBApplication.tagsHandler(ctx).changeTagSort(id, SCHEME + TagSortEntry.SORT_ZA + getName()); + } else if (stringId == R.string.menu_tag_sort_hist_rec) { + changesMade = TBApplication.tagsHandler(ctx).changeTagSort(id, SCHEME + TagSortEntry.HISTORY_REC + getName()); + } else if (stringId == R.string.menu_tag_sort_hist_freq) { + changesMade = TBApplication.tagsHandler(ctx).changeTagSort(id, SCHEME + TagSortEntry.HISTORY_FREQ + getName()); + } else if (stringId == R.string.menu_tag_sort_hist_frec) { + changesMade = TBApplication.tagsHandler(ctx).changeTagSort(id, SCHEME + TagSortEntry.HISTORY_FREC + getName()); + } else if (stringId == R.string.menu_tag_sort_hist_adaptive) { + changesMade = TBApplication.tagsHandler(ctx).changeTagSort(id, SCHEME + TagSortEntry.HISTORY_ADAPTIVE + getName()); + } + if (changesMade) { + // update providers, we're expecting the tag to be in the Dock + TBApplication.dataHandler(ctx).afterQuickListChanged(); return true; } return super.popupMenuClickHandler(view, item, stringId, parentView); @@ -67,17 +101,17 @@ public Drawable getDefaultDrawable(Context context) { private void launchRenameDialog(@NonNull Context c) { DialogHelper.makeRenameDialog(c, getName(), (dialog, newName) -> { - Context ctx = dialog.getContext(); + Context ctx = dialog.getContext(); - String oldName = getName(); + String oldName = getName(); - TBApplication app = TBApplication.getApplication(ctx); - app.tagsHandler().renameTag(oldName, newName); - app.behaviour().refreshSearchRecord(TagEntry.this); + TBApplication app = TBApplication.getApplication(ctx); + app.tagsHandler().renameTag(oldName, newName); + app.behaviour().refreshSearchRecord(TagEntry.this); - // update providers and refresh views - TagsManager.afterChangesMade(ctx); - }) + // update providers and refresh views + TagsManager.afterChangesMade(ctx); + }) .setTitle(R.string.title_rename_tag) .setHint(R.string.hint_rename_tag) .show(); diff --git a/app/src/main/java/rocks/tbog/tblauncher/entry/TagSortEntry.java b/app/src/main/java/rocks/tbog/tblauncher/entry/TagSortEntry.java index 431e09eb..27a6adae 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/entry/TagSortEntry.java +++ b/app/src/main/java/rocks/tbog/tblauncher/entry/TagSortEntry.java @@ -2,7 +2,6 @@ import android.content.Context; import android.view.View; -import android.widget.Toast; import androidx.annotation.NonNull; @@ -13,6 +12,7 @@ import rocks.tbog.tblauncher.TBApplication; import rocks.tbog.tblauncher.searcher.SortedTagSearcher; import rocks.tbog.tblauncher.ui.LinearAdapter; +import rocks.tbog.tblauncher.ui.ListPopup; public class TagSortEntry extends TagEntry { public static final String SORT_AZ = "sort/byName/"; @@ -37,8 +37,31 @@ public void setName(String name) { // find the default name from the id String action = getTagSortOrder(id); super.setName(id.substring(SCHEME.length() + action.length())); + } else { + super.setName(name); } - super.setName(name); + } + + @Override + ListPopup inflatePopupMenu(@NonNull Context context, @NonNull LinearAdapter adapter) { + // this tag is already sorted, remove the option to sort it the same + var sortOrder = getTagSortOrder(id); + for (int i = 0; i < adapter.getCount(); i += 1) { + LinearAdapter.MenuItem item = adapter.getItem(i); + if (item instanceof LinearAdapter.Item) { + var itemStringId = ((LinearAdapter.Item) item).stringId; + if ((itemStringId == R.string.menu_tag_sort_az && SORT_AZ.equals(sortOrder)) + || (itemStringId == R.string.menu_tag_sort_za && SORT_ZA.equals(sortOrder)) + || (itemStringId == R.string.menu_tag_sort_hist_rec && HISTORY_REC.equals(sortOrder)) + || (itemStringId == R.string.menu_tag_sort_hist_freq && HISTORY_FREQ.equals(sortOrder)) + || (itemStringId == R.string.menu_tag_sort_hist_frec && HISTORY_FREC.equals(sortOrder)) + || (itemStringId == R.string.menu_tag_sort_hist_adaptive && HISTORY_ADAPTIVE.equals(sortOrder))) { + adapter.remove(item); + break; + } + } + } + return super.inflatePopupMenu(context, adapter); } @Override @@ -49,42 +72,6 @@ public void doLaunch(@NonNull View v, int flags) { TBApplication.quickList(ctx).toggleSearch(v, id, SortedTagSearcher.class); } - @Override - protected void buildPopupMenuCategory(Context context, @NonNull LinearAdapter adapter, int titleStringId) { - if (titleStringId == R.string.popup_title_hist_fav) { - adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_az)); - adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_za)); - adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_hist_rec)); - adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_hist_freq)); - adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_hist_frec)); - adapter.add(new LinearAdapter.Item(context, R.string.menu_tag_sort_hist_adaptive)); - } - } - - @Override - boolean popupMenuClickHandler(@NonNull View view, @NonNull LinearAdapter.MenuItem item, int stringId, View parentView) { - if (stringId == R.string.menu_tag_sort_az) { - Toast.makeText(view.getContext(), "WIP: sort AZ", Toast.LENGTH_SHORT).show(); - return true; - } else if (stringId == R.string.menu_tag_sort_za) { - Toast.makeText(view.getContext(), "WIP: sort ZA", Toast.LENGTH_SHORT).show(); - return true; - }else if (stringId == R.string.menu_tag_sort_hist_rec) { - Toast.makeText(view.getContext(), "WIP: sort hist rec", Toast.LENGTH_SHORT).show(); - return true; - }else if (stringId == R.string.menu_tag_sort_hist_freq) { - Toast.makeText(view.getContext(), "WIP: sort hist freq", Toast.LENGTH_SHORT).show(); - return true; - }else if (stringId == R.string.menu_tag_sort_hist_frec) { - Toast.makeText(view.getContext(), "WIP: sort hist frec", Toast.LENGTH_SHORT).show(); - return true; - }else if (stringId == R.string.menu_tag_sort_hist_adaptive) { - Toast.makeText(view.getContext(), "WIP: sort hist adaptive", Toast.LENGTH_SHORT).show(); - return true; - } - return super.popupMenuClickHandler(view, item, stringId, parentView); - } - @NonNull public static String getTagSortOrder(String id) { String idWithoutScheme = id.substring(SCHEME.length()); @@ -104,7 +91,7 @@ public static String getTagSortOrder(String id) { } public static boolean isTagSort(String id) { - return !getTagSortOrder(id).isEmpty(); + return id.startsWith(SCHEME) && !getTagSortOrder(id).isEmpty(); } public static class TagDetails { diff --git a/app/src/main/java/rocks/tbog/tblauncher/handler/DataHandler.java b/app/src/main/java/rocks/tbog/tblauncher/handler/DataHandler.java index 244846d6..3a8145c6 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/handler/DataHandler.java +++ b/app/src/main/java/rocks/tbog/tblauncher/handler/DataHandler.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -579,6 +580,8 @@ public void requestAllRecords(Searcher searcher) { List pojos = entry.provider.getPojos(); if (pojos == null) continue; + for (var item : pojos) + item.resetResultInfo(); boolean accept = searcher.addResult(pojos); // if searcher will not accept any more results, exit if (!accept) @@ -649,6 +652,31 @@ public List getHistory(int itemCount, DBHelper.HistoryMode historyMod return history; } + public Map getHistoryOrder(DBHelper.HistoryMode historyMode, Set itemsToExcludeById) { + // Read history + final Context context = getContext(); + List ids = DBHelper.getHistory(context, Integer.MAX_VALUE, historyMode); + + // Pre-allocate array slots that are likely to be used + HashMap history = new HashMap<>(ids.size()); + + // Find associated items + for (int i = 0; i < ids.size(); i++) { + // Ask all providers if they know this id + EntryItem entryItem = getPojo(ids.get(i).record); + + if (entryItem == null) + continue; + + if (itemsToExcludeById.contains(entryItem.id)) + continue; + + history.put(entryItem, i); + } + + return history; + } + public boolean addShortcut(ShortcutRecord record) { final Context context = getContext(); @@ -1067,7 +1095,11 @@ public void setQuickList(Iterable records) { } } - // refresh relevant providers + afterQuickListChanged(); + } + + public void afterQuickListChanged() { + // refresh relevant providers for the Dock { IProvider provider = getModProvider(); if (provider != null) diff --git a/app/src/main/java/rocks/tbog/tblauncher/handler/TagsHandler.java b/app/src/main/java/rocks/tbog/tblauncher/handler/TagsHandler.java index 54c462e4..2f839c69 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/handler/TagsHandler.java +++ b/app/src/main/java/rocks/tbog/tblauncher/handler/TagsHandler.java @@ -95,8 +95,8 @@ public void loadFromDB(boolean wait) { apply.run(); } else { Utilities.runAsync( - (t) -> load.run(), - (t) -> apply.run()); + (t) -> load.run(), + (t) -> apply.run()); } } @@ -385,24 +385,24 @@ private String getClockApp(PackageManager pm) { // Known clock implementations // See http://stackoverflow.com/questions/3590955/intent-to-launch-the-clock-application-on-android String[][] clockImpls = { - // Nexus - {"com.android.deskclock", "com.android.deskclock.DeskClock"}, - // Samsung - {"com.sec.android.app.clockpackage", "com.sec.android.app.clockpackage.ClockPackage"}, - // HTC - {"com.htc.android.worldclock", "com.htc.android.worldclock.WorldClockTabControl"}, - // Standard Android - {"com.android.deskclock", "com.android.deskclock.AlarmClock"}, - // New Android versions - {"com.google.android.deskclock", "com.android.deskclock.AlarmClock"}, - // Froyo - {"com.google.android.deskclock", "com.android.deskclock.DeskClock"}, - // Motorola - {"com.motorola.blur.alarmclock", "com.motorola.blur.alarmclock.AlarmClock"}, - // Sony - {"com.sonyericsson.organizer", "com.sonyericsson.organizer.Organizer_WorldClock"}, - // ASUS Tablets - {"com.asus.deskclock", "com.asus.deskclock.DeskClock"} + // Nexus + {"com.android.deskclock", "com.android.deskclock.DeskClock"}, + // Samsung + {"com.sec.android.app.clockpackage", "com.sec.android.app.clockpackage.ClockPackage"}, + // HTC + {"com.htc.android.worldclock", "com.htc.android.worldclock.WorldClockTabControl"}, + // Standard Android + {"com.android.deskclock", "com.android.deskclock.AlarmClock"}, + // New Android versions + {"com.google.android.deskclock", "com.android.deskclock.AlarmClock"}, + // Froyo + {"com.google.android.deskclock", "com.android.deskclock.DeskClock"}, + // Motorola + {"com.motorola.blur.alarmclock", "com.motorola.blur.alarmclock.AlarmClock"}, + // Sony + {"com.sonyericsson.organizer", "com.sonyericsson.organizer.Organizer_WorldClock"}, + // ASUS Tablets + {"com.asus.deskclock", "com.asus.deskclock.DeskClock"} }; UserHandleCompat user = UserHandleCompat.CURRENT_USER; @@ -506,6 +506,42 @@ public boolean renameTag(String tagName, String newName) { return DBHelper.renameTag(getContext(), tagName, newName, tagEntry, newEntry) > 0; } + /** + * Replace the id of the current TagEntry with the new one. The tag name should remain + * + * @param tagId id of the TagEntry (or TagSortEntry) you want to sort + * @param newTagId id on the TagSortEntry + * @return true if at least one entry was renamed (sort order and id are linked) + */ + public boolean changeTagSort(String tagId, String newTagId) { + DataHandler dataHandler = mApplication.getDataHandler(); + // change tag id from favorites + TagEntry tagEntry = null; + TagEntry newEntry = null; + TagsProvider tagsProvider = dataHandler.getTagsProvider(); + if (tagsProvider != null) { + tagEntry = tagsProvider.findById(tagId); + if (tagEntry != null && tagEntry.hasCustomIcon()) { + newEntry = tagsProvider.getTagEntry(newTagId); + } + } + if (tagEntry == null) + tagEntry = TagsProvider.newTagEntryCheckId(tagId); + if (tagEntry == null) { + Log.e(TAG, "Can't change sort order of invalid tag id `" + tagId + "`"); + return false; + } + if (newEntry == null) + newEntry = TagsProvider.newTagEntryCheckId(newTagId); + if (newEntry == null) { + Log.e(TAG, "Can't change sort order from `" + tagId + "` to invalid tag id `" + newTagId + "`"); + return false; + } + + // rename tags from database + return DBHelper.changeTagSort(getContext(), tagEntry, newEntry) > 0; + } + /** * Remove all tags from the Entry. * We keep the DB as is, maybe later we'll reinstall the app. diff --git a/app/src/main/java/rocks/tbog/tblauncher/searcher/HistorySearcher.java b/app/src/main/java/rocks/tbog/tblauncher/searcher/HistorySearcher.java index a7163d65..6110869e 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/searcher/HistorySearcher.java +++ b/app/src/main/java/rocks/tbog/tblauncher/searcher/HistorySearcher.java @@ -36,6 +36,7 @@ protected Void doInBackground(Void param) { // int maxResults = getMaxResultCount(activity); + var processedPojos = getResultQueue(); processedPojos.clear(); List history = getHistory(activity, mHistoryMode); int order = history.size(); diff --git a/app/src/main/java/rocks/tbog/tblauncher/searcher/Searcher.java b/app/src/main/java/rocks/tbog/tblauncher/searcher/Searcher.java index cd9b47ea..72410226 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/searcher/Searcher.java +++ b/app/src/main/java/rocks/tbog/tblauncher/searcher/Searcher.java @@ -29,7 +29,8 @@ public abstract class Searcher extends AsyncTask implements ISearche public static final ExecutorService SEARCH_THREAD = Executors.newSingleThreadExecutor(); protected static final int INITIAL_CAPACITY = 50; protected final WeakReference activityWeakReference; - protected final PriorityQueue processedPojos; + // sorted queue with search results (lazy init to allow initialization after constructor) + private PriorityQueue resultQueue; protected final int maxResults; private final boolean tagsEnabled; private long start; @@ -45,7 +46,6 @@ public Searcher(ISearchActivity activity, @NonNull String query) { super(); this.query = query; activityWeakReference = new WeakReference<>(activity); - processedPojos = getPojoProcessor(activity); tagsEnabled = PrefCache.getFuzzySearchTags(activity.getContext()); maxResults = getMaxResultCount(activity.getContext()); } @@ -61,16 +61,24 @@ public String getQuery() { return query; } - protected PriorityQueue getPojoProcessor(ISearchActivity activity) { + protected PriorityQueue newResultQueue() { return new PriorityQueue<>(INITIAL_CAPACITY, EntryItem.RELEVANCE_COMPARATOR); } + @CallSuper + protected PriorityQueue getResultQueue() { + if (resultQueue == null) + return resultQueue = newResultQueue(); + return resultQueue; + } + protected int getMaxResultCount(Context context) { return PrefCache.getResultSearcherCap(context); } /** * This is called from the background thread by the providers + * * @param pojos */ @WorkerThread @@ -84,6 +92,7 @@ public boolean addResult(Collection pojos) { if (activity == null) return false; + var processedPojos = getResultQueue(); processedPojos.addAll(pojos); while (processedPojos.size() > maxResults) processedPojos.poll(); @@ -119,13 +128,13 @@ protected void onPostExecute(Void param) { // Loader should still be displayed until all the providers have finished loading searchActivity.displayLoader(!TBApplication.getApplication(activity).getDataHandler().fullLoadOverSent()); - if (this.processedPojos.isEmpty()) { + var processedPojos = getResultQueue(); + if (processedPojos.isEmpty()) { searchActivity.clearAdapter(); } else { - PriorityQueue queue = this.processedPojos; - ArrayList results = new ArrayList<>(queue.size()); - while (queue.peek() != null) { - results.add(queue.poll()); + ArrayList results = new ArrayList<>(processedPojos.size()); + while (processedPojos.peek() != null) { + results.add(processedPojos.poll()); } searchActivity.updateAdapter(results, isRefresh); diff --git a/app/src/main/java/rocks/tbog/tblauncher/searcher/SortedTagSearcher.java b/app/src/main/java/rocks/tbog/tblauncher/searcher/SortedTagSearcher.java index ec9d8681..4b32436f 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/searcher/SortedTagSearcher.java +++ b/app/src/main/java/rocks/tbog/tblauncher/searcher/SortedTagSearcher.java @@ -9,9 +9,11 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.Map; import java.util.PriorityQueue; import rocks.tbog.tblauncher.TBApplication; +import rocks.tbog.tblauncher.db.DBHelper; import rocks.tbog.tblauncher.entry.EntryItem; import rocks.tbog.tblauncher.entry.EntryWithTags; import rocks.tbog.tblauncher.entry.TagSortEntry; @@ -19,9 +21,10 @@ import rocks.tbog.tblauncher.utils.Utilities; public class SortedTagSearcher extends Searcher { - final EntryWithTags.TagDetails tagDetails; - final TagSortEntry.TagDetails tagSort; - final HashSet foundIdSet = new HashSet<>(); + private final EntryWithTags.TagDetails tagDetails; + private final TagSortEntry.TagDetails tagSort; + private final HashSet foundIdSet = new HashSet<>(); + private Map order = null; public SortedTagSearcher(ISearchActivity activity, @NonNull String tagSortId) { super(activity, tagSortId); @@ -30,7 +33,7 @@ public SortedTagSearcher(ISearchActivity activity, @NonNull String tagSortId) { } @Override - protected PriorityQueue getPojoProcessor(ISearchActivity activity) { + protected PriorityQueue newResultQueue() { return new PriorityQueue<>(INITIAL_CAPACITY, tagSort.getComparator()); } @@ -60,11 +63,33 @@ private void addProcessedPojo(EntryWithTags entryItem) { if (!foundIdSet.add(entryItem.id)) return; + if (order != null) { + var priority = order.get(entryItem); + if (priority != null) + entryItem.boostRelevance(priority); + } + + var processedPojos = getResultQueue(); processedPojos.add(entryItem); if (processedPojos.size() > maxResults) processedPojos.poll(); } + @NonNull + private DBHelper.HistoryMode getHistoryMode() { + switch (tagSort.order) { + case TagSortEntry.HISTORY_REC: + return DBHelper.HistoryMode.RECENCY; + case TagSortEntry.HISTORY_FREQ: + return DBHelper.HistoryMode.FREQUENCY; + case TagSortEntry.HISTORY_FREC: + return DBHelper.HistoryMode.FRECENCY; + case TagSortEntry.HISTORY_ADAPTIVE: + default: + return DBHelper.HistoryMode.ADAPTIVE; + } + } + @WorkerThread @Override protected Void doInBackground(Void param) { @@ -78,21 +103,17 @@ protected Void doInBackground(Void param) { switch (tagSort.order) { case TagSortEntry.SORT_AZ: case TagSortEntry.SORT_ZA: - // Request all results via "addResult" + // Request all results via "addResult", the queue will sort by name dh.requestAllRecords(this); break; case TagSortEntry.HISTORY_REC: case TagSortEntry.HISTORY_FREQ: case TagSortEntry.HISTORY_FREC: - case TagSortEntry.HISTORY_ADAPTIVE: - { - var history = dh.getHistory(Integer.MAX_VALUE, DataHandler.getHistoryMode(query), false, Collections.emptySet()); - int order = 0; - for (var entry : history) { - entry.resetResultInfo(); - entry.boostRelevance(order++); - } - addResult(history); + case TagSortEntry.HISTORY_ADAPTIVE: { + // boost relevance according to history order in `addProcessedPojo` + order = dh.getHistoryOrder(getHistoryMode(), Collections.emptySet()); + // Request all results via "addResult", the queue will sort by relevance + dh.requestAllRecords(this); break; } default: diff --git a/app/src/main/java/rocks/tbog/tblauncher/searcher/TagList.java b/app/src/main/java/rocks/tbog/tblauncher/searcher/TagList.java index c3d8aaf4..047d650a 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/searcher/TagList.java +++ b/app/src/main/java/rocks/tbog/tblauncher/searcher/TagList.java @@ -32,10 +32,10 @@ public TagList(ISearchActivity activity, @NonNull String query) { } @Override - protected PriorityQueue getPojoProcessor(ISearchActivity activity) { + protected PriorityQueue newResultQueue() { if ("untagged".equals(query)) return new PriorityQueue<>(INITIAL_CAPACITY, EntryItem.NAME_COMPARATOR); - return super.getPojoProcessor(activity); + return super.newResultQueue(); } @WorkerThread @@ -65,6 +65,7 @@ private void addProcessedPojo(EntryItem entryItem) { if (!foundIdSet.add(entryItem.id)) return; + var processedPojos = getResultQueue(); processedPojos.add(entryItem); if (processedPojos.size() > maxResults) processedPojos.poll(); diff --git a/app/src/main/java/rocks/tbog/tblauncher/searcher/TagSearcher.java b/app/src/main/java/rocks/tbog/tblauncher/searcher/TagSearcher.java index 8e7b2727..145d51a8 100644 --- a/app/src/main/java/rocks/tbog/tblauncher/searcher/TagSearcher.java +++ b/app/src/main/java/rocks/tbog/tblauncher/searcher/TagSearcher.java @@ -25,7 +25,7 @@ public TagSearcher(ISearchActivity activity, @NonNull String query) { } @Override - protected PriorityQueue getPojoProcessor(ISearchActivity activity) { + protected PriorityQueue newResultQueue() { return new PriorityQueue<>(INITIAL_CAPACITY, EntryItem.NAME_COMPARATOR); } @@ -55,6 +55,7 @@ private void addProcessedPojo(EntryWithTags entryItem) { if (!foundIdSet.add(entryItem.id)) return; + var processedPojos = getResultQueue(); processedPojos.add(entryItem); if (processedPojos.size() > maxResults) processedPojos.poll();