Put savedreply handling it its own class

multisite
Floens 9 years ago
parent 8695552b8d
commit 4a3b9058b8
  1. 2
      Clover/app/src/main/java/org/floens/chan/chan/ChanParser.java
  2. 96
      Clover/app/src/main/java/org/floens/chan/core/database/DatabaseManager.java
  3. 120
      Clover/app/src/main/java/org/floens/chan/core/database/DatabaseSavedReplyManager.java
  4. 23
      Clover/app/src/main/java/org/floens/chan/core/model/SavedReply.java
  5. 2
      Clover/app/src/main/java/org/floens/chan/core/net/ChanReaderRequest.java
  6. 3
      Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java
  7. 13
      Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
  8. 9
      Clover/app/src/main/java/org/floens/chan/ui/controller/DeveloperSettingsController.java

@ -421,7 +421,7 @@ public class ChanParser {
}
// Append You when it's a reply to an saved reply
if (databaseManager.isSavedReply(post.board, id)) {
if (databaseManager.getDatabaseSavedReplyManager().isSaved(post.board, id)) {
key += " (You)";
}
}

@ -29,9 +29,9 @@ import org.floens.chan.Chan;
import org.floens.chan.core.model.Board;
import org.floens.chan.core.model.Filter;
import org.floens.chan.core.model.Post;
import org.floens.chan.core.model.SavedReply;
import org.floens.chan.core.model.ThreadHide;
import org.floens.chan.utils.Logger;
import org.floens.chan.utils.Time;
import java.sql.SQLException;
import java.util.ArrayList;
@ -50,26 +50,19 @@ import static com.j256.ormlite.misc.TransactionManager.callInTransaction;
public class DatabaseManager {
private static final String TAG = "DatabaseManager";
private static final long SAVED_REPLY_TRIM_TRIGGER = 250;
private static final long SAVED_REPLY_TRIM_COUNT = 50;
private static final long THREAD_HIDE_TRIM_TRIGGER = 250;
private static final long THREAD_HIDE_TRIM_COUNT = 50;
private static final long HISTORY_TRIM_TRIGGER = 500;
private static final long HISTORY_TRIM_COUNT = 50;
private final ExecutorService backgroundExecutor;
private final DatabaseHelper helper;
private final Object savedRepliesLock = new Object();
private final List<SavedReply> savedReplies = new ArrayList<>();
private final HashSet<Integer> savedRepliesIds = new HashSet<>();
private final List<ThreadHide> threadHides = new ArrayList<>();
private final HashSet<Integer> threadHidesIds = new HashSet<>();
private final DatabasePinManager databasePinManager;
private final DatabaseLoadableManager databaseLoadableManager;
private final DatabaseHistoryManager databaseHistoryManager;
private final DatabaseSavedReplyManager databaseSavedReplyManager;
public DatabaseManager(Context context) {
backgroundExecutor = Executors.newSingleThreadExecutor();
@ -78,6 +71,7 @@ public class DatabaseManager {
databaseLoadableManager = new DatabaseLoadableManager(this, helper);
databasePinManager = new DatabasePinManager(this, helper, databaseLoadableManager);
databaseHistoryManager = new DatabaseHistoryManager(this, helper, databaseLoadableManager);
databaseSavedReplyManager = new DatabaseSavedReplyManager(this, helper);
initialize();
EventBus.getDefault().register(this);
}
@ -94,6 +88,10 @@ public class DatabaseManager {
return databaseHistoryManager;
}
public DatabaseSavedReplyManager getDatabaseSavedReplyManager() {
return databaseSavedReplyManager;
}
// Called when the app changes foreground state
public void onEvent(Chan.ForegroundChangedMessage message) {
if (!message.inForeground) {
@ -102,9 +100,9 @@ public class DatabaseManager {
}
private void initialize() {
loadSavedReplies();
loadThreadHides();
databaseHistoryManager.load();
runTaskSync(databaseHistoryManager.load());
runTaskSync(databaseSavedReplyManager.load());
}
/**
@ -115,59 +113,6 @@ public class DatabaseManager {
initialize();
}
/**
* Save a reply to the savedreply table.
* Threadsafe.
*
* @param saved the {@link SavedReply} to save
*/
public void saveReply(SavedReply saved) {
try {
helper.savedDao.create(saved);
} catch (SQLException e) {
Logger.e(TAG, "Error saving reply", e);
}
synchronized (savedRepliesLock) {
savedReplies.add(saved);
savedRepliesIds.add(saved.no);
}
}
/**
* Searches a saved reply. This is done through caching members, no database lookups.
* Threadsafe.
*
* @param board board for the reply to search
* @param no no for the reply to search
* @return A {@link SavedReply} that matches {@code board} and {@code no}, or {@code null}
*/
public SavedReply getSavedReply(String board, int no) {
synchronized (savedRepliesLock) {
if (savedRepliesIds.contains(no)) {
for (SavedReply r : savedReplies) {
if (r.no == no && r.board.equals(board)) {
return r;
}
}
}
}
return null;
}
/**
* Searches if a saved reply exists. This is done through caching members, no database lookups.
* Threadsafe.
*
* @param board board for the reply to search
* @param no no for the reply to search
* @return true if a {@link SavedReply} matched {@code board} and {@code no}, {@code false} otherwise
*/
public boolean isSavedReply(String board, int no) {
return getSavedReply(board, no) != null;
}
public void addOrUpdateFilter(Filter filter) {
try {
helper.filterDao.createOrUpdate(filter);
@ -317,26 +262,6 @@ public class DatabaseManager {
return o;
}
/**
* Threadsafe.
*/
private void loadSavedReplies() {
try {
trimTable(helper.savedDao, "savedreply", SAVED_REPLY_TRIM_TRIGGER, SAVED_REPLY_TRIM_COUNT);
synchronized (savedRepliesLock) {
savedReplies.clear();
savedReplies.addAll(helper.savedDao.queryForAll());
savedRepliesIds.clear();
for (SavedReply reply : savedReplies) {
savedRepliesIds.add(reply.no);
}
}
} catch (SQLException e) {
Logger.e(TAG, "Error loading saved replies", e);
}
}
private void loadThreadHides() {
try {
trimTable(helper.threadHideDao, "threadhide", THREAD_HIDE_TRIM_TRIGGER, THREAD_HIDE_TRIM_COUNT);
@ -364,8 +289,9 @@ public class DatabaseManager {
try {
long count = dao.countOf();
if (count > trigger) {
long start = Time.startTiming();
dao.executeRaw("DELETE FROM " + table + " WHERE id IN (SELECT id FROM " + table + " ORDER BY id ASC LIMIT ?)", String.valueOf(trim));
Logger.i(TAG, "Trimmed " + table + " from " + count + " to " + dao.countOf() + " rows");
Time.endTiming("Trimmed " + table + " from " + count + " to " + dao.countOf() + " rows", start);
}
} catch (SQLException e) {
Logger.e(TAG, "Error trimming table " + table, e);

@ -0,0 +1,120 @@
/*
* Clover - 4chan browser https://github.com/Floens/Clover/
* Copyright (C) 2014 Floens
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.floens.chan.core.database;
import com.j256.ormlite.stmt.QueryBuilder;
import org.floens.chan.core.model.SavedReply;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
public class DatabaseSavedReplyManager {
private static final String TAG = "DatabaseSavedReplyManager";
private static final long SAVED_REPLY_TRIM_TRIGGER = 250;
private static final long SAVED_REPLY_TRIM_COUNT = 50;
private DatabaseManager databaseManager;
private DatabaseHelper helper;
private final Object lock = new Object();
private final Map<Integer, List<SavedReply>> savedRepliesByNo = new HashMap<>();
public DatabaseSavedReplyManager(DatabaseManager databaseManager, DatabaseHelper helper) {
this.databaseManager = databaseManager;
this.helper = helper;
}
// optimized and threadsafe
public boolean isSaved(String board, int no) {
synchronized (lock) {
if (savedRepliesByNo.containsKey(no)) {
List<SavedReply> items = savedRepliesByNo.get(no);
for (int i = 0; i < items.size(); i++) {
SavedReply item = items.get(i);
if (item.board.equals(board)) {
return true;
}
}
return false;
} else {
return false;
}
}
}
public Callable<Void> load() {
return new Callable<Void>() {
@Override
public Void call() throws Exception {
databaseManager.trimTable(helper.savedDao, "savedreply", SAVED_REPLY_TRIM_TRIGGER, SAVED_REPLY_TRIM_COUNT);
final List<SavedReply> all = helper.savedDao.queryForAll();
synchronized (lock) {
savedRepliesByNo.clear();
for (int i = 0; i < all.size(); i++) {
SavedReply savedReply = all.get(i);
if (savedRepliesByNo.containsKey(savedReply.no)) {
savedRepliesByNo.get(savedReply.no).add(savedReply);
} else {
List<SavedReply> items = new ArrayList<>();
items.add(savedReply);
savedRepliesByNo.put(savedReply.no, items);
}
}
}
return null;
}
};
}
public Callable<SavedReply> saveReply(final SavedReply savedReply) {
return new Callable<SavedReply>() {
@Override
public SavedReply call() throws Exception {
helper.savedDao.create(savedReply);
synchronized (lock) {
if (savedRepliesByNo.containsKey(savedReply.no)) {
savedRepliesByNo.get(savedReply.no).add(savedReply);
} else {
List<SavedReply> items = new ArrayList<>();
items.add(savedReply);
savedRepliesByNo.put(savedReply.no, items);
}
}
return savedReply;
}
};
}
public Callable<SavedReply> findSavedReply(final String board, final int no) {
return new Callable<SavedReply>() {
@Override
public SavedReply call() throws Exception {
QueryBuilder<SavedReply, Integer> builder = helper.savedDao.queryBuilder();
List<SavedReply> query = builder.where().eq("board", board).and().eq("no", no).query();
return query.isEmpty() ? null : query.get(0);
}
};
}
}

@ -34,12 +34,29 @@ public class SavedReply {
@DatabaseField(generatedId = true)
private int id;
@DatabaseField
public String board = "";
@DatabaseField(index = true, canBeNull = false)
public String board;
@DatabaseField
@DatabaseField(index = true)
public int no;
@DatabaseField
public String password = "";
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SavedReply that = (SavedReply) o;
return no == that.no && board.equals(that.board);
}
@Override
public int hashCode() {
int result = board.hashCode();
result = 31 * result + no;
return result;
}
}

@ -378,7 +378,7 @@ public class ChanReaderRequest extends JsonReaderRequest<ChanReaderRequest.ChanR
}
private void processPostAfterFinish(Post post) {
post.isSavedReply = databaseManager.isSavedReply(post.board, post.no);
post.isSavedReply = databaseManager.getDatabaseSavedReplyManager().isSaved(post.board, post.no);
}
public static class ChanReaderResponse {

@ -214,7 +214,8 @@ public class ReplyPresenter implements ReplyManager.HttpCallback<ReplyHttpCall>,
}
}
databaseManager.saveReply(new SavedReply(loadable.board, replyCall.postNo, replyCall.password));
SavedReply savedReply = new SavedReply(loadable.board, replyCall.postNo, replyCall.password);
databaseManager.runTask(databaseManager.getDatabaseSavedReplyManager().saveReply(savedReply));
switchPage(Page.INPUT, false);
closeAll();

@ -430,7 +430,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
}
}
if (databaseManager.isSavedReply(post.board, post.no)) {
if (databaseManager.getDatabaseSavedReplyManager().isSaved(post.board, post.no)) {
menu.add(new FloatingMenuItem(POST_OPTION_DELETE, R.string.delete));
}
@ -476,7 +476,8 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
requestDeletePost(post);
break;
case POST_OPTION_SAVE:
databaseManager.saveReply(new SavedReply(post.board, post.no, "foo"));
SavedReply savedReply = new SavedReply(post.board, post.no, "");
databaseManager.runTask(databaseManager.getDatabaseSavedReplyManager().saveReply(savedReply));
break;
case POST_OPTION_PIN:
Loadable pinLoadable = databaseManager.getDatabaseLoadableManager().get(Loadable.forThread(post.board, post.no));
@ -584,7 +585,9 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
public void deletePostConfirmed(Post post, boolean onlyImageDelete) {
threadPresenterCallback.showDeleting();
SavedReply reply = databaseManager.getSavedReply(post.board, post.no);
SavedReply reply = databaseManager.runTaskSync(
databaseManager.getDatabaseSavedReplyManager().findSavedReply(post.board, post.no)
);
if (reply != null) {
replyManager.makeHttpCall(new DeleteHttpCall(reply, onlyImageDelete), new ReplyManager.HttpCallback<DeleteHttpCall>() {
@Override
@ -609,7 +612,9 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
}
private void requestDeletePost(Post post) {
SavedReply reply = databaseManager.getSavedReply(post.board, post.no);
SavedReply reply = databaseManager.runTaskSync(
databaseManager.getDatabaseSavedReplyManager().findSavedReply(post.board, post.no)
);
if (reply != null) {
threadPresenterCallback.confirmPostDelete(post);
}

@ -27,6 +27,7 @@ import android.widget.TextView;
import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
import org.floens.chan.core.database.DatabaseManager;
import org.floens.chan.core.model.SavedReply;
import java.util.Random;
@ -37,6 +38,8 @@ import static org.floens.chan.utils.AndroidUtils.getAttrColor;
public class DeveloperSettingsController extends Controller {
private TextView summaryText;
private DatabaseManager databaseManager;
public DeveloperSettingsController(Context context) {
super(context);
}
@ -45,6 +48,8 @@ public class DeveloperSettingsController extends Controller {
public void onCreate() {
super.onCreate();
databaseManager = Chan.getDatabaseManager();
navigationItem.setTitle(R.string.settings_developer);
LinearLayout wrapper = new LinearLayout(context);
@ -87,7 +92,9 @@ public class DeveloperSettingsController extends Controller {
int j = 0;
for (int i = 0; i < 100; i++) {
j += r.nextInt(10000);
Chan.getDatabaseManager().saveReply(new SavedReply("g", j, "pass"));
SavedReply saved = new SavedReply("g", j, "");
databaseManager.runTask(databaseManager.getDatabaseSavedReplyManager().saveReply(saved));
}
setDbSummary();
}

Loading…
Cancel
Save