diff --git a/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseHideManager.java b/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseHideManager.java new file mode 100644 index 00000000..f5981af4 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseHideManager.java @@ -0,0 +1,118 @@ +package org.floens.chan.core.database; + +import com.j256.ormlite.table.TableUtils; + +import org.floens.chan.core.model.Post; +import org.floens.chan.core.model.orm.ThreadHide; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +public class DatabaseHideManager { + private static final long THREAD_HIDE_TRIM_TRIGGER = 250; + private static final long THREAD_HIDE_TRIM_COUNT = 50; + + private DatabaseManager databaseManager; + private DatabaseHelper helper; + + private final Map> hides = new HashMap<>(); + + public DatabaseHideManager(DatabaseManager databaseManager, DatabaseHelper helper) { + this.databaseManager = databaseManager; + this.helper = helper; + } + + public Callable load() { + return () -> { + databaseManager.trimTable(helper.threadHideDao, "threadhide", + THREAD_HIDE_TRIM_TRIGGER, THREAD_HIDE_TRIM_COUNT); + + synchronized (hides) { + hides.clear(); + + List threadHides = helper.threadHideDao.queryForAll(); + for (ThreadHide hide : threadHides) { + List hidesForId = hides.get(hide.no); + if (hidesForId == null) { + hidesForId = new ArrayList<>(1); + hides.put(hide.no, hidesForId); + } + + hidesForId.add(hide); + } + } + + return null; + }; + } + + /** + * Returns if the given post is hidden. The Post must be a OP of a thread. + *

+ * This method is thread-safe, and doesn't need to be called through + * {@link DatabaseManager#runTask(Callable)}. + * + * @param post The Post to check if it is hidden. + * @return {@code true} if hidden, {@code false} otherwise. + */ + public boolean isThreadHidden(Post post) { + synchronized (hides) { + if (hides.containsKey(post.no)) { + for (ThreadHide threadHide : hides.get(post.no)) { + if (threadHide.equalsPost(post)) { + return true; + } + } + } + } + return false; + } + + public Callable addThreadHide(ThreadHide hide) { + return () -> { + helper.threadHideDao.create(hide); + + synchronized (hides) { + List hidesForId = hides.get(hide.no); + if (hidesForId == null) { + hidesForId = new ArrayList<>(1); + hides.put(hide.no, hidesForId); + } + + hidesForId.add(hide); + } + + return null; + }; + } + + public Callable removeThreadHide(ThreadHide hide) { + return () -> { + helper.threadHideDao.delete(hide); + + synchronized (hides) { + List hidesForId = hides.get(hide.no); + if (hidesForId != null) { + hidesForId.remove(hide); + } + } + + return null; + }; + } + + public Callable clearAllThreadHides() { + return () -> { + TableUtils.clearTable(helper.getConnectionSource(), ThreadHide.class); + + synchronized (hides) { + hides.clear(); + } + + return null; + }; + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseManager.java b/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseManager.java index 4424df6c..36fbacd2 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseManager.java @@ -24,18 +24,12 @@ import android.support.annotation.NonNull; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.misc.TransactionManager; -import com.j256.ormlite.table.TableUtils; import org.floens.chan.Chan; -import org.floens.chan.core.model.Post; -import org.floens.chan.core.model.orm.ThreadHide; import org.floens.chan.utils.Logger; import org.floens.chan.utils.Time; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -61,16 +55,10 @@ import de.greenrobot.event.EventBus; public class DatabaseManager { private static final String TAG = "DatabaseManager"; - private static final long THREAD_HIDE_TRIM_TRIGGER = 250; - private static final long THREAD_HIDE_TRIM_COUNT = 50; - private final ExecutorService backgroundExecutor; private Thread executorThread; private final DatabaseHelper helper; - private final List threadHides = new ArrayList<>(); - private final HashSet threadHidesIds = new HashSet<>(); - private final DatabasePinManager databasePinManager; private final DatabaseLoadableManager databaseLoadableManager; private final DatabaseHistoryManager databaseHistoryManager; @@ -78,6 +66,7 @@ public class DatabaseManager { private final DatabaseFilterManager databaseFilterManager; private final DatabaseBoardManager databaseBoardManager; private final DatabaseSiteManager databaseSiteManager; + private final DatabaseHideManager databaseHideManager; @Inject public DatabaseManager(Context context) { @@ -91,6 +80,7 @@ public class DatabaseManager { databaseFilterManager = new DatabaseFilterManager(this, helper); databaseBoardManager = new DatabaseBoardManager(this, helper); databaseSiteManager = new DatabaseSiteManager(this, helper); + databaseHideManager = new DatabaseHideManager(this, helper); initialize(); EventBus.getDefault().register(this); } @@ -123,6 +113,10 @@ public class DatabaseManager { return databaseSiteManager; } + public DatabaseHideManager getDatabaseHideManager() { + return databaseHideManager; + } + // Called when the app changes foreground state public void onEvent(Chan.ForegroundChangedMessage message) { if (!message.inForeground) { @@ -131,13 +125,12 @@ public class DatabaseManager { } private void initialize() { - loadThreadHides(); - // Loads data into fields. runTask(databaseSavedReplyManager.load()); // Only trims. runTaskAsync(databaseHistoryManager.load()); + runTaskAsync(databaseHideManager.load()); } /** @@ -148,67 +141,6 @@ public class DatabaseManager { initialize(); } - /** - * Check if the post is added in the threadhide table. - * - * @param post Post to check the board and no on - * @return true if it was hidden, false otherwise - */ - public boolean isThreadHidden(Post post) { - if (threadHidesIds.contains(post.no)) { - for (ThreadHide hide : threadHides) { - if (hide.no == post.no && hide.board.equals(post.boardId)) { - return true; - } - } - } - return false; - } - - /** - * Adds an entry to the threadhide table and updates any caching members. - * - * @param threadHide The {@link ThreadHide} to add. - */ - public void addThreadHide(ThreadHide threadHide) { - try { - helper.threadHideDao.create(threadHide); - threadHides.add(threadHide); - threadHidesIds.add(threadHide.no); - } catch (SQLException e) { - Logger.e(TAG, "Error adding threadhide", e); - } - } - - /** - * Removes the entry from the threadhide table and updates any caching members. - * - * @param threadHide The {@link ThreadHide} to remove. - */ - public void removeThreadHide(ThreadHide threadHide) { - try { - helper.threadHideDao.delete(threadHide); - threadHides.remove(threadHide); - // ThreadHidesIds not removed because there may be another post with the same id on another board - // It's just an caching thing, it'll reset itself after a restart - } catch (SQLException e) { - Logger.e(TAG, "Error deleting threadhide", e); - } - } - - /** - * Clears all {@link ThreadHide}s from the table and resets any caching members. - */ - public void clearAllThreadHides() { - try { - TableUtils.clearTable(helper.getConnectionSource(), ThreadHide.class); - threadHides.clear(); - threadHidesIds.clear(); - } catch (SQLException e) { - Logger.e(TAG, "Error clearing threadhide table", e); - } - } - /** * Summary of the database tables row count, for the developer screen. * @@ -225,6 +157,7 @@ public class DatabaseManager { o += "ThreadHide rows: " + helper.threadHideDao.countOf() + "\n"; o += "History rows: " + helper.historyDao.countOf() + "\n"; o += "Filter rows: " + helper.filterDao.countOf() + "\n"; + o += "Site rows: " + helper.siteDao.countOf() + "\n"; } catch (SQLException e) { e.printStackTrace(); } @@ -232,21 +165,6 @@ public class DatabaseManager { return o; } - private void loadThreadHides() { - try { - trimTable(helper.threadHideDao, "threadhide", THREAD_HIDE_TRIM_TRIGGER, THREAD_HIDE_TRIM_COUNT); - - threadHides.clear(); - threadHides.addAll(helper.threadHideDao.queryForAll()); - threadHidesIds.clear(); - for (ThreadHide hide : threadHides) { - threadHidesIds.add(hide.no); - } - } catch (SQLException e) { - Logger.e(TAG, "Error loading thread hides", e); - } - } - /** * Trim a table with the specified trigger and trim count. * diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/orm/ThreadHide.java b/Clover/app/src/main/java/org/floens/chan/core/model/orm/ThreadHide.java index a352ebd8..dba8a7e1 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/model/orm/ThreadHide.java +++ b/Clover/app/src/main/java/org/floens/chan/core/model/orm/ThreadHide.java @@ -20,6 +20,8 @@ package org.floens.chan.core.model.orm; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; +import org.floens.chan.core.model.Post; + @DatabaseTable(tableName = "threadhide") public class ThreadHide { @DatabaseField(generatedId = true) @@ -37,9 +39,12 @@ public class ThreadHide { public ThreadHide() { } - public ThreadHide(String board, int no) { - this.board = board; - this.no = no; + public static ThreadHide fromPost(Post post) { + ThreadHide hide = new ThreadHide(); + hide.board = post.board.code; + hide.no = post.no; + hide.site = post.board.siteId; + return hide; } @Override @@ -49,7 +54,7 @@ public class ThreadHide { ThreadHide that = (ThreadHide) o; - return no == that.no && board.equals(that.board); + return no == that.no && board.equals(that.board) && site == that.site; } @Override @@ -58,4 +63,8 @@ public class ThreadHide { result = 31 * result + no; return result; } + + public boolean equalsPost(Post post) { + return post.no == no && board.equals(post.board.code) && post.board.siteId == site; + } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostsFilter.java b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostsFilter.java index 964cf4b0..3c5bb1cf 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostsFilter.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostsFilter.java @@ -135,7 +135,8 @@ public class PostsFilter { Iterator i = posts.iterator(); while (i.hasNext()) { Post post = i.next(); - if (post.filterRemove || databaseManager.isThreadHidden(post)) { + if (post.filterRemove || + databaseManager.getDatabaseHideManager().isThreadHidden(post)) { i.remove(); } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/BehaviourSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/BehaviourSettingsController.java index 7151649a..1208e8d6 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/BehaviourSettingsController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/BehaviourSettingsController.java @@ -160,7 +160,8 @@ public class BehaviourSettingsController extends SettingsController { public void onClick(View v) { // TODO: don't do this here. DatabaseManager databaseManager = injector().instance(DatabaseManager.class); - databaseManager.clearAllThreadHides(); + databaseManager.runTask( + databaseManager.getDatabaseHideManager().clearAllThreadHides()); Toast.makeText(context, R.string.setting_cleared_thread_hides, Toast.LENGTH_LONG) .show(); EventBus.getDefault().post(new RefreshUIMessage("clearhides")); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java index 29dcb744..70442eed 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java @@ -440,15 +440,18 @@ public class ThreadLayout extends CoordinatorLayout implements @Override public void hideThread(Post post) { - final ThreadHide threadHide = new ThreadHide(post.boardId, post.no); - databaseManager.addThreadHide(threadHide); + final ThreadHide threadHide = ThreadHide.fromPost(post); + databaseManager.runTask( + databaseManager.getDatabaseHideManager().addThreadHide(threadHide)); + presenter.refreshUI(); Snackbar snackbar = Snackbar.make(this, R.string.post_hidden, Snackbar.LENGTH_LONG); snackbar.setAction(R.string.undo, new OnClickListener() { @Override public void onClick(View v) { - databaseManager.removeThreadHide(threadHide); + databaseManager.runTask( + databaseManager.getDatabaseHideManager().removeThreadHide(threadHide)); presenter.refreshUI(); } }).show();