From 18d06e2f5776e17e49207c247a14feb94a38b685 Mon Sep 17 00:00:00 2001 From: Floens Date: Tue, 26 Dec 2017 00:01:04 +0100 Subject: [PATCH] update filter handling for multisite still messy, the controller desperately needs a presenter. --- .../chan/core/manager/FilterEngine.java | 92 +++++++--------- .../core/site/common/ChanReaderRequest.java | 11 +- .../chan/ui/controller/FiltersController.java | 2 +- .../floens/chan/ui/helper/BoardHelper.java | 22 ++++ .../floens/chan/ui/layout/FilterLayout.java | 103 ++++++------------ .../res/layout/layout_site_board_select.xml | 36 ------ 6 files changed, 94 insertions(+), 172 deletions(-) delete mode 100644 Clover/app/src/main/res/layout/layout_site_board_select.xml diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/FilterEngine.java b/Clover/app/src/main/java/org/floens/chan/core/manager/FilterEngine.java index f72f8deb..9f3e7ae2 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/manager/FilterEngine.java +++ b/Clover/app/src/main/java/org/floens/chan/core/manager/FilterEngine.java @@ -22,13 +22,13 @@ import android.text.TextUtils; import org.floens.chan.core.database.DatabaseFilterManager; import org.floens.chan.core.database.DatabaseManager; -import org.floens.chan.core.model.orm.Filter; import org.floens.chan.core.model.Post; -import org.floens.chan.core.site.Sites; +import org.floens.chan.core.model.orm.Board; +import org.floens.chan.core.model.orm.Filter; +import org.floens.chan.ui.helper.BoardHelper; import org.floens.chan.utils.Logger; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -67,21 +67,6 @@ public class FilterEngine { } } - // This is messy but required now that we can't know the Board immediately. - public static class SiteIdBoardCode { - public final int siteId; - public final String boardCode; - - private SiteIdBoardCode(int site, String board) { - siteId = site; - boardCode = board; - } - - public static SiteIdBoardCode fromSiteIdBoardCode(int siteId, String boardCode) { - return new SiteIdBoardCode(siteId, boardCode); - } - } - private final DatabaseManager databaseManager; private final BoardManager boardManager; @@ -116,7 +101,42 @@ public class FilterEngine { return enabledFilters; } - // threadsafe + @AnyThread + public boolean matchesBoard(Filter filter, Board board) { + if (filter.allBoards || TextUtils.isEmpty(filter.boards)) { + return true; + } else { + for (String uniqueId : filter.boards.split(",")) { + if (BoardHelper.matchesUniqueId(board, uniqueId)) { + return true; + } + } + return false; + } + } + + public int getFilterBoardCount(Filter filter) { + if (filter.allBoards) { + return -1; + } else { + return filter.boards.split(",").length; + } + } + + public void saveBoardsToFilter(List appliedBoards, boolean all, Filter filter) { + filter.allBoards = all; + if (all) { + filter.boards = ""; + } else { + List boardsString = new ArrayList<>(appliedBoards.size()); + for (int i = 0; i < appliedBoards.size(); i++) { + boardsString.add(BoardHelper.boardUniqueId(appliedBoards.get(i))); + } + filter.boards = TextUtils.join(",", boardsString); + } + } + + @AnyThread public boolean matches(Filter filter, Post.Builder post) { if ((filter.type & FilterType.TRIPCODE.flag) != 0 && matches(filter, FilterType.TRIPCODE.isRegex, post.tripcode, false)) { return true; @@ -236,40 +256,6 @@ public class FilterEngine { return pattern; } - public List getBoardsForFilter(Filter filter) { - if (filter.allBoards) { - return Collections.emptyList(); - } else if (!TextUtils.isEmpty(filter.boards)) { - List appliedBoards = new ArrayList<>(); - for (String value : filter.boards.split(",")) { - if (value.contains(";")) { - String[] siteAndBoard = value.split(";"); - if (siteAndBoard.length == 1) { - appliedBoards.add(SiteIdBoardCode.fromSiteIdBoardCode(Integer.parseInt(siteAndBoard[0]), "")); - } else { - appliedBoards.add(SiteIdBoardCode.fromSiteIdBoardCode(Integer.parseInt(siteAndBoard[0]), siteAndBoard[1])); - } - } else { - appliedBoards.add(SiteIdBoardCode.fromSiteIdBoardCode(Sites.defaultSite().id(), value)); - } - } - return appliedBoards; - } else { - return Collections.emptyList(); - } - } - - public void saveBoardsToFilter(List appliedBoards, Filter filter) { - filter.boards = ""; - for (int i = 0; i < appliedBoards.size(); i++) { - SiteIdBoardCode siteAndBoard = appliedBoards.get(i); - filter.boards += siteAndBoard.siteId + ";" + siteAndBoard.boardCode; - if (i < appliedBoards.size() - 1) { - filter.boards += ","; - } - } - } - private String escapeRegex(String filthy) { return filterFilthyPattern.matcher(filthy).replaceAll("\\\\$1"); // Escape regex special characters with a \ } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java index e4394b0a..34fa06cf 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java @@ -91,18 +91,9 @@ public class ChanReaderRequest extends JsonReaderRequest { for (int i = 0; i < enabledFilters.size(); i++) { Filter filter = enabledFilters.get(i); - if (filter.allBoards) { + if (filterEngine.matchesBoard(filter, loadable.board)) { // copy the filter because it will get used on other threads filters.add(filter.copy()); - } else { - String[] boardCodes = filter.boardCodes(); - for (String code : boardCodes) { - if (code.equals(loadable.boardCode)) { - // copy the filter because it will get used on other threads - filters.add(filter.copy()); - break; - } - } } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/FiltersController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/FiltersController.java index 2ecb83d1..b3fd9fde 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/FiltersController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/FiltersController.java @@ -216,7 +216,7 @@ public class FiltersController extends Controller implements ToolbarMenuItem.Too if (filter.allBoards) { subText += context.getString(R.string.filter_summary_all_boards); } else { - int size = filterEngine.getBoardsForFilter(filter).size(); + int size = filterEngine.getFilterBoardCount(filter); subText += context.getResources().getQuantityString(R.plurals.board, size, size); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/helper/BoardHelper.java b/Clover/app/src/main/java/org/floens/chan/ui/helper/BoardHelper.java index 45c85626..4358354d 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/helper/BoardHelper.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/helper/BoardHelper.java @@ -73,4 +73,26 @@ public class BoardHelper { name * 5 + Math.max(0, description - 30) * 8; } + + public static String boardUniqueId(Board board) { + String code = board.code.replace(":", "").replace(",", ""); + return board.site.id() + ":" + code; + } + + public static boolean matchesUniqueId(Board board, String uniqueId) { + if (!uniqueId.contains(":")) { + return board.site.id() == 0 && board.code.equals(uniqueId); + } else { + String[] splitted = uniqueId.split(":"); + if (splitted.length != 2) { + return false; + } + + try { + return Integer.parseInt(splitted[0]) == board.site.id() && splitted[1].equals(board.code); + } catch (NumberFormatException ignored) { + return false; + } + } + } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/FilterLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/FilterLayout.java index e7a3b706..858fa0a6 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/FilterLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/FilterLayout.java @@ -17,6 +17,7 @@ */ package org.floens.chan.ui.layout; +import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.graphics.Typeface; @@ -33,29 +34,23 @@ import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; import android.widget.CheckBox; -import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.Spinner; -import android.widget.SpinnerAdapter; import android.widget.TextView; import org.floens.chan.R; import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.manager.FilterEngine; import org.floens.chan.core.manager.FilterType; +import org.floens.chan.core.model.orm.Board; import org.floens.chan.core.model.orm.Filter; -import org.floens.chan.core.site.Site; -import org.floens.chan.core.site.Sites; import org.floens.chan.ui.controller.FiltersController; import org.floens.chan.ui.dialog.ColorPickerView; import org.floens.chan.ui.drawable.DropdownArrowDrawable; +import org.floens.chan.ui.helper.BoardHelper; import org.floens.chan.ui.view.FloatingMenu; import org.floens.chan.ui.view.FloatingMenuItem; -import org.floens.chan.utils.Logger; import java.util.ArrayList; import java.util.List; @@ -90,8 +85,6 @@ public class FilterLayout extends LinearLayout implements View.OnClickListener { private FilterLayoutCallback callback; private Filter filter; - private List appliedBoards = new ArrayList<>(); - public FilterLayout(Context context) { super(context); } @@ -168,8 +161,6 @@ public class FilterLayout extends LinearLayout implements View.OnClickListener { public void setFilter(Filter filter) { this.filter = filter; - appliedBoards.clear(); - appliedBoards.addAll(filterEngine.getBoardsForFilter(filter)); pattern.setText(filter.pattern); @@ -188,16 +179,15 @@ public class FilterLayout extends LinearLayout implements View.OnClickListener { public Filter getFilter() { filter.enabled = enabled.isChecked(); - filterEngine.saveBoardsToFilter(appliedBoards, filter); - return filter; } @Override public void onClick(View v) { if (v == typeText) { - @SuppressWarnings("unchecked") - final SelectLayout selectLayout = (SelectLayout) LayoutInflater.from(getContext()).inflate(R.layout.layout_select, null); + @SuppressWarnings("unchecked") final SelectLayout selectLayout = + (SelectLayout) LayoutInflater.from(getContext()) + .inflate(R.layout.layout_select, null); List> items = new ArrayList<>(); for (FilterType filterType : FilterType.values()) { @@ -232,75 +222,44 @@ public class FilterLayout extends LinearLayout implements View.OnClickListener { }) .show(); } else if (v == boardsSelector) { - // TODO(multi-site): fix this crap. - // we need a new proper recyclerview layout where you can individually select each site and board combination - // and if you don't select anything, it becomes a global filter. - - final LinearLayout selectLayout = (LinearLayout) LayoutInflater.from(getContext()) - .inflate(R.layout.layout_site_board_select, null); + @SuppressLint("InflateParams") @SuppressWarnings("unchecked") final SelectLayout selectLayout = + (SelectLayout) LayoutInflater.from(getContext()) + .inflate(R.layout.layout_select, null); - final Spinner spinner = (Spinner) selectLayout.findViewById(R.id.progress); + List> items = new ArrayList<>(); - final List allSites = Sites.allSites(); - - final Site[] selectedSite = {allSites.get(0)}; - - List allSitesNames = new ArrayList<>(allSites.size()); - for (int i = 0; i < allSites.size(); i++) { - Site site = allSites.get(i); - allSitesNames.add(site.name()); - } + for (Board board : boardManager.getSavedBoards()) { + String name = BoardHelper.getName(board); + boolean checked = filterEngine.matchesBoard(filter, board); - SpinnerAdapter adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, allSitesNames); - spinner.setAdapter(adapter); - - spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - Site site = allSites.get(position); - selectedSite[0] = site; - Logger.test(site.name()); - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - - final EditText editText = (EditText) selectLayout.findViewById(R.id.boards); - - String text = ""; - for (int i = 0; i < appliedBoards.size(); i++) { - FilterEngine.SiteIdBoardCode siteIdBoardCode = appliedBoards.get(i); - text += siteIdBoardCode.boardCode; - if (i < appliedBoards.size() - 1) { - text += ","; - } + items.add(new SelectLayout.SelectItem<>( + board, board.id, name, "", name, checked + )); } - editText.setText(text); + selectLayout.setItems(items); new AlertDialog.Builder(getContext()) .setView(selectLayout) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - Site site = selectedSite[0]; - - appliedBoards.clear(); - - String[] codes = editText.getText().toString().split(","); - if (codes.length == 0) { - filter.allBoards = true; - } else { - filter.allBoards = false; - for (String code : codes) { - appliedBoards.add(FilterEngine.SiteIdBoardCode.fromSiteIdBoardCode( - site.id(), code - )); + List> items = selectLayout.getItems(); + boolean all = selectLayout.areAllChecked(); + List boardList = new ArrayList<>(items.size()); + if (!all) { + for (SelectLayout.SelectItem item : items) { + if (item.checked) { + boardList.add(item.item); + } + } + if (boardList.isEmpty()) { + all = true; } } + filterEngine.saveBoardsToFilter(boardList, all, filter); + updateBoardsSummary(); } }) @@ -392,7 +351,7 @@ public class FilterLayout extends LinearLayout implements View.OnClickListener { if (filter.allBoards) { text += getString(R.string.filter_all); } else { - text += String.valueOf(appliedBoards.size()); + text += filterEngine.getFilterBoardCount(filter); } text += ")"; boardsSelector.setText(text); diff --git a/Clover/app/src/main/res/layout/layout_site_board_select.xml b/Clover/app/src/main/res/layout/layout_site_board_select.xml deleted file mode 100644 index d358d30c..00000000 --- a/Clover/app/src/main/res/layout/layout_site_board_select.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - -