add boardrepository

make siterepository the owner of site instances
refactor-toolbar
Floens 7 years ago
parent a91cc5155c
commit 7ef0243922
  1. 8
      Clover/app/src/main/java/org/floens/chan/Chan.java
  2. 123
      Clover/app/src/main/java/org/floens/chan/core/database/DatabaseBoardManager.java
  3. 6
      Clover/app/src/main/java/org/floens/chan/core/database/DatabaseLoadableManager.java
  4. 41
      Clover/app/src/main/java/org/floens/chan/core/database/DatabaseManager.java
  5. 4
      Clover/app/src/main/java/org/floens/chan/core/database/DatabaseSavedReplyManager.java
  6. 121
      Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java
  7. 31
      Clover/app/src/main/java/org/floens/chan/core/model/orm/Board.java
  8. 12
      Clover/app/src/main/java/org/floens/chan/core/presenter/BoardsMenuPresenter.java
  9. 12
      Clover/app/src/main/java/org/floens/chan/core/presenter/BrowsePresenter.java
  10. 87
      Clover/app/src/main/java/org/floens/chan/core/presenter/SitesSetupPresenter.java
  11. 189
      Clover/app/src/main/java/org/floens/chan/core/repository/BoardRepository.java
  12. 249
      Clover/app/src/main/java/org/floens/chan/core/repository/SiteRepository.java
  13. 16
      Clover/app/src/main/java/org/floens/chan/core/site/SiteBase.java
  14. 63
      Clover/app/src/main/java/org/floens/chan/core/site/SiteRepository.java
  15. 15
      Clover/app/src/main/java/org/floens/chan/core/site/SiteResolver.java
  16. 123
      Clover/app/src/main/java/org/floens/chan/core/site/SiteService.java
  17. 35
      Clover/app/src/main/java/org/floens/chan/core/site/Sites.java
  18. 6
      Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java
  19. 30
      Clover/app/src/main/java/org/floens/chan/ui/controller/SitesSetupController.java
  20. 7
      Clover/app/src/main/java/org/floens/chan/ui/layout/FilterLayout.java

@ -31,6 +31,7 @@ import org.floens.chan.core.database.DatabaseManager;
import org.floens.chan.core.di.AppModule;
import org.floens.chan.core.di.NetModule;
import org.floens.chan.core.di.UserAgentProvider;
import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.site.SiteService;
import org.floens.chan.utils.AndroidUtils;
import org.floens.chan.utils.Logger;
@ -52,11 +53,14 @@ public class Chan extends Application implements UserAgentProvider, Application.
private String userAgent;
private int activityForegroundCounter = 0;
@Inject
DatabaseManager databaseManager;
@Inject
SiteService siteService;
@Inject
DatabaseManager databaseManager;
BoardManager boardManager;
private Feather feather;
@ -94,6 +98,8 @@ public class Chan extends Application implements UserAgentProvider, Application.
initializeGraph();
siteService.initialize();
boardManager.initialize();
databaseManager.initializeAndTrim();
Time.endTiming("Initializing application", startTime);

@ -1,14 +1,23 @@
package org.floens.chan.core.database;
import android.annotation.SuppressLint;
import android.util.Pair;
import com.j256.ormlite.stmt.PreparedUpdate;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.SelectArg;
import com.j256.ormlite.stmt.UpdateBuilder;
import org.floens.chan.core.model.orm.Board;
import org.floens.chan.core.model.orm.SiteModel;
import org.floens.chan.core.site.Site;
import org.floens.chan.utils.Time;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
public class DatabaseBoardManager {
@ -29,9 +38,9 @@ public class DatabaseBoardManager {
.and().eq("value", board.code);
Board existing = q.queryForFirst();
if (existing != null) {
existing.updateExcudingUserFields(board);
existing.updateExcludingUserFields(board);
helper.boardsDao.update(existing);
board.updateExcudingUserFields(existing);
board.updateExcludingUserFields(existing);
} else {
helper.boardsDao.create(board);
}
@ -80,22 +89,62 @@ public class DatabaseBoardManager {
};
}
public Callable<Void> createAll(final List<Board> boards) {
public Callable<Void> createAll(final Site site, final List<Board> boards) {
return () -> {
// TODO: optimize
long start = Time.startTiming();
List<Board> allFromDb = helper.boardsDao.queryForEq("site", site.id());
Map<String, Board> byCodeFromDb = new HashMap<>();
for (Board board : allFromDb) {
byCodeFromDb.put(board.code, board);
board.site = site;
}
List<Board> toCreate = new ArrayList<>();
List<Pair<Board, Board>> toUpdate = new ArrayList<>();
for (Board board : boards) {
if (byCodeFromDb.containsKey(board.code)) {
Board dbBoard = byCodeFromDb.get(board.code);
if (!dbBoard.propertiesEqual(board)) {
toUpdate.add(new Pair<>(dbBoard, board));
}
} else {
toCreate.add(board);
}
}
if (!toCreate.isEmpty()) {
for (Board board : toCreate) {
helper.boardsDao.create(board);
}
}
if (!toUpdate.isEmpty()) {
for (Pair<Board, Board> pair : toUpdate) {
Board dbBoard = pair.first;
Board newPropertiesBoard = pair.second;
dbBoard.updateExcludingUserFields(newPropertiesBoard);
helper.boardsDao.update(dbBoard);
}
}
/*for (Board board : boards) {
QueryBuilder<Board, Integer> q = helper.boardsDao.queryBuilder();
q.where().eq("site", board.getSite().id())
.and().eq("value", board.code);
Board existing = q.queryForFirst();
if (existing != null) {
existing.updateExcudingUserFields(board);
existing.updateExcludingUserFields(board);
helper.boardsDao.update(existing);
board.updateExcudingUserFields(existing);
board.updateExcludingUserFields(existing);
} else {
helper.boardsDao.create(board);
}
}
}*/
Time.endTiming("createAll boards " +
toCreate.size() + ", " + toUpdate.size(), start);
return null;
};
@ -116,6 +165,66 @@ public class DatabaseBoardManager {
};
}
@SuppressLint("UseSparseArrays")
public Callable<List<Pair<Site, List<Board>>>> getBoardsForAllSitesOrdered(List<Site> sites) {
return () -> {
long start = Time.startTiming();
// Query the orders of the sites.
QueryBuilder<SiteModel, Integer> q = helper.siteDao.queryBuilder();
q.selectColumns("id", "order");
List<SiteModel> modelsWithOrder = q.query();
Map<Integer, Integer> ordering = new HashMap<>();
for (SiteModel siteModel : modelsWithOrder) {
ordering.put(siteModel.id, siteModel.order);
}
List<Site> sitesOrdered = new ArrayList<>(sites);
// Sort the given sites array with these orders.
Collections.sort(sitesOrdered,
(lhs, rhs) -> ordering.get(lhs.id()) - ordering.get(rhs.id()));
// Query all boards belonging to any of these sites.
List<Integer> siteIds = new ArrayList<>(sitesOrdered.size());
for (Site site : sitesOrdered) {
siteIds.add(site.id());
}
List<Board> allBoards = helper.boardsDao.queryBuilder()
.where().in("site", siteIds)
.query();
// Map the boards from siteId to a list of boards.
Map<Integer, Site> sitesById = new HashMap<>();
for (Site site : sites) {
sitesById.put(site.id(), site);
}
Map<Integer, List<Board>> bySite = new HashMap<>();
for (Board board : allBoards) {
board.site = sitesById.get(board.siteId);
List<Board> boards = bySite.get(board.siteId);
if (boards == null) {
boards = new ArrayList<>();
bySite.put(board.siteId, boards);
}
boards.add(board);
}
// And map the site to the board, and order these boards.
List<Pair<Site, List<Board>>> res = new ArrayList<>();
for (Site site : sitesOrdered) {
List<Board> siteBoards = bySite.get(site.id());
if (siteBoards == null) siteBoards = new ArrayList<>();
Collections.sort(siteBoards, (lhs, rhs) -> lhs.order - rhs.order);
res.add(new Pair<>(site, siteBoards));
}
Time.endTiming("getBoardsForAllSitesOrdered", start);
return res;
};
}
public Callable<List<Board>> getSiteBoards(final Site site) {
return () -> {
List<Board> boards = helper.boardsDao.queryBuilder()

@ -22,7 +22,7 @@ import android.util.Log;
import com.j256.ormlite.stmt.QueryBuilder;
import org.floens.chan.core.model.orm.Loadable;
import org.floens.chan.core.site.Sites;
import org.floens.chan.core.repository.SiteRepository;
import org.floens.chan.utils.Logger;
import org.floens.chan.utils.Time;
@ -124,7 +124,7 @@ public class DatabaseLoadableManager {
// Add it to the cache, refresh contents
helper.loadableDao.refresh(loadable);
loadable.site = Sites.forId(loadable.siteId);
loadable.site = SiteRepository.forId(loadable.siteId);
loadable.board = loadable.site.board(loadable.boardCode);
cachedLoadables.put(loadable, loadable);
return loadable;
@ -165,7 +165,7 @@ public class DatabaseLoadableManager {
result = loadable;
} else {
Log.d(TAG, "Loadable found in db");
result.site = Sites.forId(result.siteId);
result.site = SiteRepository.forId(result.siteId);
result.board = result.site.board(result.boardCode);
}

@ -33,8 +33,9 @@ import java.sql.SQLException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -70,7 +71,10 @@ public class DatabaseManager {
@Inject
public DatabaseManager(Context context) {
backgroundExecutor = Executors.newSingleThreadExecutor();
backgroundExecutor = new ThreadPoolExecutor(
1, 1,
1000L, TimeUnit.DAYS,
new LinkedBlockingQueue<>());
helper = new DatabaseHelper(context);
databaseLoadableManager = new DatabaseLoadableManager(this, helper);
@ -81,10 +85,18 @@ public class DatabaseManager {
databaseBoardManager = new DatabaseBoardManager(this, helper);
databaseSiteManager = new DatabaseSiteManager(this, helper);
databaseHideManager = new DatabaseHideManager(this, helper);
initialize();
EventBus.getDefault().register(this);
}
public void initializeAndTrim() {
// Loads data into fields.
runTask(databaseSavedReplyManager.load());
// Only trims.
runTaskAsync(databaseHistoryManager.load());
runTaskAsync(databaseHideManager.load());
}
public DatabasePinManager getDatabasePinManager() {
return databasePinManager;
}
@ -116,29 +128,20 @@ public class DatabaseManager {
public DatabaseHideManager getDatabaseHideManager() {
return databaseHideManager;
}
// Called when the app changes foreground state
public void onEvent(Chan.ForegroundChangedMessage message) {
if (!message.inForeground) {
runTaskAsync(databaseLoadableManager.flush());
}
}
private void initialize() {
// Loads data into fields.
runTask(databaseSavedReplyManager.load());
// Only trims.
runTaskAsync(databaseHistoryManager.load());
runTaskAsync(databaseHideManager.load());
}
/**
* Reset all tables in the database. Used for the developer screen.
*/
public void reset() {
helper.reset();
initialize();
initializeAndTrim();
}
/**
@ -187,7 +190,8 @@ public class DatabaseManager {
}
public <T> void runTaskAsync(final Callable<T> taskCallable) {
runTaskAsync(taskCallable, null);
runTaskAsync(taskCallable, result -> {
});
}
public <T> void runTaskAsync(final Callable<T> taskCallable, final TaskResult<T> taskResult) {
@ -254,12 +258,7 @@ public class DatabaseManager {
try {
final T result = TransactionManager.callInTransaction(helper.getConnectionSource(), taskCallable);
if (taskResult != null) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
taskResult.onComplete(result);
}
});
new Handler(Looper.getMainLooper()).post(() -> taskResult.onComplete(result));
}
return result;
} catch (Exception e) {

@ -24,7 +24,7 @@ import com.j256.ormlite.table.TableUtils;
import org.floens.chan.core.model.orm.Board;
import org.floens.chan.core.model.orm.SavedReply;
import org.floens.chan.core.site.Sites;
import org.floens.chan.core.repository.SiteRepository;
import org.floens.chan.utils.Time;
import java.util.ArrayList;
@ -92,7 +92,7 @@ public class DatabaseSavedReplyManager {
for (int i = 0; i < all.size(); i++) {
SavedReply savedReply = all.get(i);
savedReply.site = Sites.forId(savedReply.siteId);
savedReply.site = SiteRepository.forId(savedReply.siteId);
List<SavedReply> list = savedRepliesByNo.get(savedReply.no);
if (list == null) {

@ -17,20 +17,11 @@
*/
package org.floens.chan.core.manager;
import android.util.Pair;
import org.floens.chan.core.database.DatabaseBoardManager;
import org.floens.chan.core.database.DatabaseManager;
import org.floens.chan.core.model.orm.Board;
import org.floens.chan.core.repository.BoardRepository;
import org.floens.chan.core.site.Site;
import org.floens.chan.core.site.SiteService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -48,46 +39,22 @@ import javax.inject.Singleton;
* favorite board list, along with a {@link Board#order} in which they appear.
*/
@Singleton
public class BoardManager implements Observer {
public class BoardManager {
private static final String TAG = "BoardManager";
private static final Comparator<Board> ORDER_SORT = (lhs, rhs) -> lhs.order - rhs.order;
private final DatabaseManager databaseManager;
private final DatabaseBoardManager databaseBoardManager;
private final SiteService siteService;
private final SiteService.SitesChangedObservable sitesChangedObservable;
private final AllBoards allBoardsObservable = new AllBoards();
private final SavedBoards savedBoardsObservable = new SavedBoards();
private final List<Pair<Site, List<Board>>> sitesWithBoards = new ArrayList<>();
private final List<Pair<Site, List<Board>>> sitesWithSavedBoards = new ArrayList<>();
private final BoardRepository boardRepository;
@Inject
public BoardManager(DatabaseManager databaseManager, SiteService siteService) {
this.databaseManager = databaseManager;
this.siteService = siteService;
sitesChangedObservable = siteService.getSitesChangedObservable();
databaseBoardManager = databaseManager.getDatabaseBoardManager();
updateObservables();
sitesChangedObservable.addObserver(this);
public BoardManager(BoardRepository boardRepository) {
this.boardRepository = boardRepository;
}
@Override
public void update(Observable o, Object arg) {
// If the sites changed (added, removed or reordered) we need to reload the boards.
if (o == sitesChangedObservable) {
updateObservables();
}
public void initialize() {
boardRepository.initialize();
}
public void createAll(List<Board> boards) {
databaseManager.runTask(databaseBoardManager.createAll(boards));
public void updateAvailableBoardsForSite(Site site, List<Board> boards) {
boardRepository.updateAvailableBoardsForSite(site, boards);
}
/**
@ -99,84 +66,34 @@ public class BoardManager implements Observer {
* @return the board code with the same site and board code, or {@code null} if not found.
*/
public Board getBoard(Site site, String code) {
return databaseManager.runTask(databaseBoardManager.getBoard(site, code));
return boardRepository.getFromCode(site, code);
}
public List<Board> getSiteBoards(Site site) {
List<Board> boards = databaseManager.runTask(databaseBoardManager.getSiteBoards(site));
Collections.sort(boards, ORDER_SORT);
return boards;
return boardRepository.getSiteBoards(site);
}
public List<Board> getSiteSavedBoards(Site site) {
List<Board> boards = databaseManager.runTask(databaseBoardManager.getSiteSavedBoards(site));
Collections.sort(boards, ORDER_SORT);
return boards;
return boardRepository.getSiteSavedBoards(site);
}
public AllBoards getAllBoardsObservable() {
return allBoardsObservable;
public BoardRepository.SitesBoards getAllBoardsObservable() {
return boardRepository.getAll();
}
public SavedBoards getSavedBoardsObservable() {
return savedBoardsObservable;
public BoardRepository.SitesBoards getSavedBoardsObservable() {
return boardRepository.getSaved();
}
public void updateBoardOrders(List<Board> boards) {
databaseManager.runTask(databaseBoardManager.updateOrders(boards));
updateObservables();
boardRepository.updateBoardOrders(boards);
}
public void setSaved(Board board, boolean saved) {
board.saved = saved;
databaseManager.runTask(databaseBoardManager.updateIncludingUserFields(board));
updateObservables();
boardRepository.setSaved(board, saved);
}
public void setAllSaved(List<Board> boards, boolean saved) {
for (Board board : boards) {
board.saved = saved;
}
databaseManager.runTask(databaseBoardManager.updateIncludingUserFields(boards));
updateObservables();
}
private void updateObservables() {
sitesWithBoards.clear();
for (Site site : siteService.getAllSitesInOrder()) {
List<Board> all = getSiteBoards(site);
sitesWithBoards.add(new Pair<>(site, all));
List<Board> saved = new ArrayList<>();
for (Board siteBoard : all) {
if (siteBoard.saved) saved.add(siteBoard);
}
sitesWithSavedBoards.add(new Pair<>(site, saved));
}
allBoardsObservable.doNotify();
savedBoardsObservable.doNotify();
}
public class AllBoards extends Observable {
private void doNotify() {
setChanged();
notifyObservers();
}
public List<Pair<Site, List<Board>>> get() {
return sitesWithBoards;
}
}
public class SavedBoards extends Observable {
private void doNotify() {
setChanged();
notifyObservers();
}
public List<Pair<Site, List<Board>>> get() {
return sitesWithSavedBoards;
}
boardRepository.setAllSaved(boards, saved);
}
}

@ -17,6 +17,7 @@
*/
package org.floens.chan.core.model.orm;
import android.support.v4.util.ObjectsCompat;
import android.text.TextUtils;
import com.j256.ormlite.field.DatabaseField;
@ -180,7 +181,7 @@ public class Board implements SiteReference {
*
* @param o other board to update from.
*/
public void updateExcudingUserFields(Board o) {
public void updateExcludingUserFields(Board o) {
siteId = o.siteId;
site = o.site;
name = o.name;
@ -249,4 +250,32 @@ public class Board implements SiteReference {
b.archive = archive;
return b;
}
public boolean propertiesEqual(Board b) {
return name.equals(b.name) &&
code.equals(b.code) &&
workSafe == b.workSafe &&
perPage == b.perPage &&
pages == b.pages &&
maxFileSize == b.maxFileSize &&
maxWebmSize == b.maxWebmSize &&
maxCommentChars == b.maxCommentChars &&
bumpLimit == b.bumpLimit &&
imageLimit == b.imageLimit &&
cooldownThreads == b.cooldownThreads &&
cooldownReplies == b.cooldownReplies &&
cooldownImages == b.cooldownImages &&
cooldownRepliesIntra == b.cooldownRepliesIntra &&
cooldownImagesIntra == b.cooldownImagesIntra &&
spoilers == b.spoilers &&
customSpoilers == b.customSpoilers &&
userIds == b.userIds &&
codeTags == b.codeTags &&
preuploadCaptcha == b.preuploadCaptcha &&
countryFlags == b.countryFlags &&
trollFlags == b.trollFlags &&
mathTags == b.mathTags &&
ObjectsCompat.equals(description, b.description) &&
archive == b.archive;
}
}

@ -18,10 +18,10 @@
package org.floens.chan.core.presenter;
import android.support.annotation.Nullable;
import android.util.Pair;
import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.model.orm.Board;
import org.floens.chan.core.repository.BoardRepository;
import org.floens.chan.core.site.Site;
import org.floens.chan.ui.helper.BoardHelper;
@ -34,7 +34,7 @@ import javax.inject.Inject;
public class BoardsMenuPresenter implements Observer {
private Callback callback;
private BoardManager.AllBoards allBoards;
private BoardRepository.SitesBoards allBoards;
private Items items;
@ -89,14 +89,14 @@ public class BoardsMenuPresenter implements Observer {
public Items() {
}
public void update(List<Pair<Site, List<Board>>> allBoards, String filter) {
public void update(List<BoardRepository.SiteBoards> allBoards, String filter) {
items.clear();
items.add(new Item(0, Item.Type.SEARCH));
for (Pair<Site, List<Board>> siteAndBoards : allBoards) {
Site site = siteAndBoards.first;
List<Board> boards = siteAndBoards.second;
for (BoardRepository.SiteBoards siteAndBoards : allBoards) {
Site site = siteAndBoards.site;
List<Board> boards = siteAndBoards.boards;
items.add(new Item(itemIdCounter++, site));

@ -17,15 +17,13 @@
*/
package org.floens.chan.core.presenter;
import android.util.Pair;
import org.floens.chan.core.database.DatabaseManager;
import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.model.orm.Board;
import org.floens.chan.core.model.orm.Loadable;
import org.floens.chan.core.repository.BoardRepository;
import org.floens.chan.core.site.Site;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
@ -39,7 +37,7 @@ public class BrowsePresenter implements Observer {
private boolean hadBoards = false;
private Board currentBoard;
private BoardManager.SavedBoards savedBoardsObservable;
private BoardRepository.SitesBoards savedBoardsObservable;
@Inject
public BrowsePresenter(DatabaseManager databaseManager, BoardManager boardManager) {
@ -99,9 +97,9 @@ public class BrowsePresenter implements Observer {
}
private Board firstBoard() {
for (Pair<Site, List<Board>> siteListPair : savedBoardsObservable.get()) {
if (!siteListPair.second.isEmpty()) {
return siteListPair.second.get(0);
for (BoardRepository.SiteBoards item : savedBoardsObservable.get()) {
if (!item.boards.isEmpty()) {
return item.boards.get(0);
}
}
return null;

@ -20,55 +20,78 @@ package org.floens.chan.core.presenter;
import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.site.Site;
import org.floens.chan.core.repository.SiteRepository;
import org.floens.chan.core.site.SiteService;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import javax.inject.Inject;
public class SitesSetupPresenter {
private SiteService siteService;
private BoardManager boardManager;
public class SitesSetupPresenter implements Observer {
private final SiteService siteService;
private final SiteRepository siteRepository;
private final BoardManager boardManager;
private Callback callback;
private AddCallback addCallback;
private List<Site> sites = new ArrayList<>();
private SiteRepository.Sites sites;
private List<Site> sitesShown = new ArrayList<>();
@Inject
public SitesSetupPresenter(SiteService siteService, BoardManager boardManager) {
public SitesSetupPresenter(SiteService siteService, SiteRepository siteRepository,
BoardManager boardManager) {
this.siteService = siteService;
this.siteRepository = siteRepository;
this.boardManager = boardManager;
}
public void create(Callback callback) {
this.callback = callback;
sites.addAll(siteService.getAllSitesInOrder());
sites = siteRepository.all();
sites.addObserver(this);
this.callback.setAddedSites(sites);
sitesShown.addAll(sites.getAllInOrder());
this.callback.setNextAllowed(!sites.isEmpty());
updateSitesInUi();
if (sites.isEmpty()) {
this.callback.setNextAllowed(!sitesShown.isEmpty());
if (sitesShown.isEmpty()) {
callback.presentIntro();
}
}
public void destroy() {
sites.deleteObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if (o == sites) {
sitesShown.clear();
sitesShown.addAll(sites.getAllInOrder());
updateSitesInUi();
}
}
public void show() {
callback.setAddedSites(sites);
updateSitesInUi();
}
public void move(int from, int to) {
Site item = sites.remove(from);
sites.add(to, item);
Site item = sitesShown.remove(from);
sitesShown.add(to, item);
saveOrder();
callback.setAddedSites(sites);
updateSitesInUi();
}
public void onIntroDismissed() {
if (sites.isEmpty()) {
if (sitesShown.isEmpty()) {
callback.showHint();
}
}
@ -82,7 +105,7 @@ public class SitesSetupPresenter {
}
public boolean mayExit() {
return sites.size() > 0;
return sitesShown.size() > 0;
}
public void onShowDialogClicked() {
@ -111,17 +134,13 @@ public class SitesSetupPresenter {
public void onDoneClicked() {
}
public int getSiteBoardCount(Site site) {
return boardManager.getSiteSavedBoards(site).size();
}
private void siteAdded(Site site) {
sites.add(site);
sitesShown.add(site);
saveOrder();
callback.setAddedSites(sites);
updateSitesInUi();
callback.setNextAllowed(!sites.isEmpty());
callback.setNextAllowed(!sitesShown.isEmpty());
}
public void onSiteCellSettingsClicked(Site site) {
@ -129,18 +148,36 @@ public class SitesSetupPresenter {
}
private void saveOrder() {
siteService.updateOrdering(sites);
siteService.updateOrdering(sitesShown);
}
private void updateSitesInUi() {
List<SiteBoardCount> r = new ArrayList<>();
for (Site site : sitesShown) {
r.add(new SiteBoardCount(site, boardManager.getSiteSavedBoards(site).size()));
}
callback.setSites(r);
}
public class SiteBoardCount {
public Site site;
public int boardCount;
public SiteBoardCount(Site site, int boardCount) {
this.site = site;
this.boardCount = boardCount;
}
}
public interface Callback {
void setSites(List<SiteBoardCount> sites);
void presentIntro();
void showHint();
void showAddDialog();
void setAddedSites(List<Site> sites);
void setNextAllowed(boolean nextAllowed);
void openSiteConfiguration(Site site);

@ -0,0 +1,189 @@
/*
* 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.repository;
import android.util.Pair;
import org.floens.chan.core.database.DatabaseBoardManager;
import org.floens.chan.core.database.DatabaseManager;
import org.floens.chan.core.model.orm.Board;
import org.floens.chan.core.site.Site;
import org.floens.chan.utils.Time;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class BoardRepository implements Observer {
private final DatabaseManager databaseManager;
private final DatabaseBoardManager databaseBoardManager;
private final SiteRepository siteRepository;
private final SiteRepository.Sites allSites;
private SitesBoards allBoards = new SitesBoards();
private SitesBoards savedBoards = new SitesBoards();
@Inject
public BoardRepository(DatabaseManager databaseManager, SiteRepository siteRepository) {
this.databaseManager = databaseManager;
databaseBoardManager = databaseManager.getDatabaseBoardManager();
this.siteRepository = siteRepository;
allSites = this.siteRepository.all();
allSites.addObserver(this);
}
public void initialize() {
updateObservablesSync();
}
@Override
public void update(Observable o, Object arg) {
if (o == allSites) {
updateObservablesAsync();
}
}
public void updateAvailableBoardsForSite(Site site, List<Board> availableBoards) {
databaseManager.runTask(databaseBoardManager.createAll(site, availableBoards));
}
public Board getFromCode(Site site, String code) {
for (SiteBoards siteBoards : allBoards.get()) {
if (siteBoards.site.id() == site.id()) {
for (Board board : siteBoards.boards) {
if (board.code.equals(code)) {
return board;
}
}
return null;
}
}
return null;
}
public SitesBoards getAll() {
return allBoards;
}
public SitesBoards getSaved() {
return savedBoards;
}
public List<Board> getSiteBoards(Site site) {
for (SiteBoards item : allBoards.siteBoards) {
if (item.site.id() == site.id()) {
return item.boards;
}
}
return new ArrayList<>();
}
public List<Board> getSiteSavedBoards(Site site) {
for (SiteBoards item : savedBoards.siteBoards) {
if (item.site.id() == site.id()) {
return item.boards;
}
}
return new ArrayList<>();
}
public void updateBoardOrders(List<Board> boards) {
databaseManager.runTaskAsync(databaseBoardManager.updateOrders(boards),
(e) -> updateObservablesAsync());
}
public void setSaved(Board board, boolean saved) {
board.saved = saved;
databaseManager.runTaskAsync(databaseBoardManager.updateIncludingUserFields(board),
(e) -> updateObservablesAsync());
}
public void setAllSaved(List<Board> boards, boolean saved) {
for (Board board : boards) {
board.saved = saved;
}
databaseManager.runTaskAsync(databaseBoardManager.updateIncludingUserFields(boards),
(e) -> updateObservablesAsync());
}
private void updateObservablesSync() {
long start = Time.startTiming();
updateWith(databaseManager.runTask(
databaseBoardManager.getBoardsForAllSitesOrdered(allSites.getAll())));
Time.endTiming("BoardRepository.updateObservablesSync", start);
}
private void updateObservablesAsync() {
databaseManager.runTaskAsync(
databaseBoardManager.getBoardsForAllSitesOrdered(allSites.getAll()),
this::updateWith);
}
private void updateWith(List<Pair<Site, List<Board>>> databaseData) {
List<SiteBoards> all = new ArrayList<>();
List<SiteBoards> saved = new ArrayList<>();
for (Pair<Site, List<Board>> item : databaseData) {
all.add(new SiteBoards(item.first, item.second));
List<Board> savedBoards = new ArrayList<>();
for (Board board : item.second) {
if (board.saved) savedBoards.add(board);
}
saved.add(new SiteBoards(item.first, savedBoards));
}
allBoards.set(all);
savedBoards.set(saved);
allBoards.notifyObservers();
savedBoards.notifyObservers();
}
public class SitesBoards extends Observable {
private List<SiteBoards> siteBoards = new ArrayList<>();
public void set(List<SiteBoards> siteBoards) {
this.siteBoards = siteBoards;
setChanged();
}
public List<SiteBoards> get() {
return siteBoards;
}
}
public class SiteBoards {
public final Site site;
public final List<Board> boards;
public SiteBoards(Site site, List<Board> boards) {
this.site = site;
this.boards = boards;
}
}
}

@ -0,0 +1,249 @@
package org.floens.chan.core.repository;
import android.util.Pair;
import android.util.SparseArray;
import org.floens.chan.core.database.DatabaseManager;
import org.floens.chan.core.model.json.site.SiteConfig;
import org.floens.chan.core.model.orm.SiteModel;
import org.floens.chan.core.settings.json.JsonSettings;
import org.floens.chan.core.site.Site;
import org.floens.chan.core.site.SiteRegistry;
import org.floens.chan.core.site.sites.chan4.Chan4;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class SiteRepository {
private DatabaseManager databaseManager;
private Sites sitesObservable = new Sites();
// Shortcut
private static SiteRepository instance;
public static Site forId(int id) {
return instance.sitesObservable.forId(id);
}
@Inject
public SiteRepository(DatabaseManager databaseManager) {
instance = this;
this.databaseManager = databaseManager;
}
public Sites all() {
return sitesObservable;
}
public SiteModel byId(int id) {
return databaseManager.runTask(databaseManager.getDatabaseSiteManager()
.byId(id));
}
public void setId(SiteModel siteModel, int id) {
databaseManager.runTask(databaseManager.getDatabaseSiteManager()
.updateId(siteModel, id));
}
public void updateSiteUserSettingsAsync(SiteModel siteModel, JsonSettings jsonSettings) {
siteModel.storeUserSettings(jsonSettings);
databaseManager.runTaskAsync(databaseManager.getDatabaseSiteManager()
.update(siteModel));
}
public Map<Integer, Integer> getOrdering() {
return databaseManager.runTask(databaseManager.getDatabaseSiteManager().getOrdering());
}
public void updateSiteOrderingAsync(List<Site> sites) {
List<Integer> ids = new ArrayList<>(sites.size());
for (Site site : sites) {
ids.add(site.id());
}
databaseManager.runTaskAsync(
databaseManager.getDatabaseSiteManager().updateOrdering(ids),
(r) -> {
sitesObservable.wasReordered();
sitesObservable.notifyObservers();
});
}
public void initialize() {
List<Site> sites = new ArrayList<>();
List<SiteModel> models = databaseManager.runTask(
databaseManager.getDatabaseSiteManager().getAll());
for (SiteModel siteModel : models) {
SiteConfigSettingsHolder holder = instantiateSiteFromModel(siteModel);
Site site = holder.site;
SiteConfig config = holder.config;
JsonSettings settings = holder.settings;
site.initialize(siteModel.id, config, settings);
sites.add(site);
}
sitesObservable.addAll(sites);
for (Site site : sites) {
site.postInitialize();
}
sitesObservable.notifyObservers();
}
// Called before #initialize to add the old 4chan site when the database was upgraded from
// an older version. It only adds the model to the database with id 0.
public void addLegacySite() {
Site site = new Chan4();
SiteConfig config = new SiteConfig();
config.classId = SiteRegistry.SITE_CLASSES.indexOfValue(site.getClass());
config.external = false;
SiteModel model = createFromClass(config, new JsonSettings());
setId(model, 0);
}
public Site createFromClass(Class<? extends Site> siteClass) {
Site site = instantiateSiteClass(siteClass);
SiteConfig config = new SiteConfig();
JsonSettings settings = new JsonSettings();
config.classId = SiteRegistry.SITE_CLASSES.indexOfValue(site.getClass());
config.external = false;
SiteModel model = createFromClass(config, settings);
site.initialize(model.id, config, settings);
sitesObservable.add(site);
site.postInitialize();
sitesObservable.notifyObservers();
return site;
}
private SiteModel createFromClass(SiteConfig config, JsonSettings userSettings) {
SiteModel siteModel = new SiteModel();
siteModel.storeConfig(config);
siteModel.storeUserSettings(userSettings);
databaseManager.runTask(databaseManager.getDatabaseSiteManager().add(siteModel));
return siteModel;
}
private SiteConfigSettingsHolder instantiateSiteFromModel(SiteModel siteModel) {
Pair<SiteConfig, JsonSettings> configFields = siteModel.loadConfigFields();
SiteConfig config = configFields.first;
JsonSettings settings = configFields.second;
return new SiteConfigSettingsHolder(
instantiateSiteClass(config.classId),
config,
settings);
}
private Site instantiateSiteClass(int classId) {
Class<? extends Site> clazz = SiteRegistry.SITE_CLASSES.get(classId);
if (clazz == null) {
throw new IllegalArgumentException("Unknown class id");
}
return instantiateSiteClass(clazz);
}
private Site instantiateSiteClass(Class<? extends Site> clazz) {
Site site;
try {
site = clazz.newInstance();
} catch (InstantiationException e) {
throw new IllegalArgumentException();
} catch (IllegalAccessException e) {
throw new IllegalArgumentException();
}
return site;
}
public class Sites extends Observable {
private List<Site> sites = Collections.unmodifiableList(new ArrayList<>());
private SparseArray<Site> sitesById = new SparseArray<>();
public Site forId(int id) {
Site s = sitesById.get(id);
if (s == null) {
throw new IllegalArgumentException("No site with id (" + id + ")");
}
return s;
}
public List<Site> getAll() {
return new ArrayList<>(sites);
}
public List<Site> getAllInOrder() {
Map<Integer, Integer> ordering = getOrdering();
List<Site> ordered = new ArrayList<>(sites);
Collections.sort(ordered,
(lhs, rhs) -> ordering.get(lhs.id()) - ordering.get(rhs.id()));
return ordered;
}
private void addAll(List<Site> all) {
List<Site> copy = new ArrayList<>(sites);
copy.addAll(all);
resetSites(copy);
setChanged();
}
private void add(Site site) {
List<Site> copy = new ArrayList<>(sites);
copy.add(site);
resetSites(copy);
setChanged();
}
// We don't keep the order ourselves here, that's the task of listeners. Do notify the
// listeners.
private void wasReordered() {
setChanged();
}
private void resetSites(List<Site> newSites) {
sites = Collections.unmodifiableList(newSites);
SparseArray<Site> byId = new SparseArray<>(newSites.size());
for (Site newSite : newSites) {
byId.put(newSite.id(), newSite);
}
sitesById = byId;
}
}
private class SiteConfigSettingsHolder {
Site site;
SiteConfig config;
JsonSettings settings;
public SiteConfigSettingsHolder(Site site, SiteConfig config, JsonSettings settings) {
this.site = site;
this.config = config;
this.settings = settings;
}
}
}

@ -30,6 +30,7 @@ import org.floens.chan.core.settings.SettingProvider;
import org.floens.chan.core.settings.json.JsonSettings;
import org.floens.chan.core.settings.json.JsonSettingsProvider;
import org.floens.chan.core.site.http.HttpCallManager;
import org.floens.chan.utils.Time;
import java.util.ArrayList;
import java.util.Collections;
@ -49,15 +50,24 @@ public abstract class SiteBase implements Site {
private JsonSettings userSettings;
protected SettingProvider settingsProvider;
private boolean initialized = false;
@Override
public void initialize(int id, SiteConfig config, JsonSettings userSettings) {
this.id = id;
this.config = config;
this.userSettings = userSettings;
if (initialized) {
throw new IllegalStateException();
}
initialized = true;
}
@Override
public void postInitialize() {
long start = Time.startTiming();
Feather injector = injector();
httpCallManager = injector.instance(HttpCallManager.class);
requestQueue = injector.instance(RequestQueue.class);
@ -72,8 +82,10 @@ public abstract class SiteBase implements Site {
initializeSettings();
if (boardsType().canList) {
actions().boards(boards -> boardManager.createAll(boards.boards));
actions().boards(boards -> boardManager.updateAvailableBoardsForSite(this, boards.boards));
}
Time.endTiming("initialized " + name(), start);
}
@Override
@ -102,7 +114,7 @@ public abstract class SiteBase implements Site {
}
Board board = Board.fromSiteNameCode(this, name, code);
boardManager.createAll(Collections.singletonList(board));
boardManager.updateAvailableBoardsForSite(this, Collections.singletonList(board));
return board;
}
}

@ -1,63 +0,0 @@
package org.floens.chan.core.site;
import org.floens.chan.core.database.DatabaseManager;
import org.floens.chan.core.model.json.site.SiteConfig;
import org.floens.chan.core.model.orm.SiteModel;
import org.floens.chan.core.settings.json.JsonSettings;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
public class SiteRepository {
private DatabaseManager databaseManager;
@Inject
public SiteRepository(DatabaseManager databaseManager) {
this.databaseManager = databaseManager;
}
public List<SiteModel> all() {
return databaseManager.runTask(databaseManager.getDatabaseSiteManager().getAll());
}
public SiteModel byId(int id) {
return databaseManager.runTask(databaseManager.getDatabaseSiteManager()
.byId(id));
}
public SiteModel create(SiteConfig config, JsonSettings userSettings) {
SiteModel siteModel = new SiteModel();
siteModel.storeConfig(config);
siteModel.storeUserSettings(userSettings);
databaseManager.runTask(databaseManager.getDatabaseSiteManager().add(siteModel));
return siteModel;
}
public void setId(SiteModel siteModel, int id) {
databaseManager.runTask(databaseManager.getDatabaseSiteManager()
.updateId(siteModel, id));
}
public void updateSiteUserSettingsAsync(SiteModel siteModel, JsonSettings jsonSettings) {
siteModel.storeUserSettings(jsonSettings);
databaseManager.runTaskAsync(databaseManager.getDatabaseSiteManager()
.update(siteModel));
}
public Map<Integer, Integer> getOrdering() {
return databaseManager.runTask(databaseManager.getDatabaseSiteManager().getOrdering());
}
public void updateSiteOrderingAsync(List<Site> sites, Runnable done) {
List<Integer> ids = new ArrayList<>(sites.size());
for (Site site : sites) {
ids.add(site.id());
}
databaseManager.runTaskAsync(databaseManager.getDatabaseSiteManager().updateOrdering(ids),
result -> done.run());
}
}

@ -22,6 +22,7 @@ import android.support.annotation.Nullable;
import org.floens.chan.core.database.LoadableProvider;
import org.floens.chan.core.model.orm.Loadable;
import org.floens.chan.core.repository.SiteRepository;
import java.util.List;
@ -30,18 +31,22 @@ import javax.inject.Inject;
import okhttp3.HttpUrl;
public class SiteResolver {
private LoadableProvider loadableProvider;
private final SiteRepository siteRepository;
private final LoadableProvider loadableProvider;
@Inject
public SiteResolver(LoadableProvider loadableProvider) {
public SiteResolver(SiteRepository siteRepository, LoadableProvider loadableProvider) {
this.siteRepository = siteRepository;
this.loadableProvider = loadableProvider;
}
public Site findSiteForUrl(String url) {
HttpUrl httpUrl = sanitizeUrl(url);
SiteRepository.Sites sites = siteRepository.all();
if (httpUrl == null) {
for (Site site : Sites.allSites()) {
for (Site site : sites.getAll()) {
SiteUrlHandler siteUrlHandler = site.resolvable();
if (siteUrlHandler.matchesName(url)) {
@ -56,7 +61,7 @@ public class SiteResolver {
httpUrl = httpUrl.newBuilder().scheme("https").build();
}
for (Site site : Sites.allSites()) {
for (Site site : sites.getAll()) {
SiteUrlHandler siteUrlHandler = site.resolvable();
if (siteUrlHandler.respondsTo(httpUrl)) {
return site;
@ -104,7 +109,7 @@ public class SiteResolver {
return null;
}
for (Site site : Sites.allSites()) {
for (Site site : siteRepository.all().getAll()) {
if (site.resolvable().respondsTo(httpUrl)) {
Loadable resolved = loadableProvider.get(
site.resolvable().resolveLoadable(site, httpUrl));

@ -18,18 +18,11 @@
package org.floens.chan.core.site;
import android.util.Pair;
import org.floens.chan.core.model.json.site.SiteConfig;
import org.floens.chan.core.model.orm.SiteModel;
import org.floens.chan.core.repository.SiteRepository;
import org.floens.chan.core.settings.json.JsonSettings;
import org.floens.chan.core.site.sites.chan4.Chan4;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -50,21 +43,14 @@ public class SiteService {
private boolean initialized = false;
private SitesChangedObservable sitesChangedObservable = new SitesChangedObservable();
@Inject
public SiteService(SiteRepository siteRepository,
SiteResolver resolver) {
public SiteService(SiteRepository siteRepository, SiteResolver resolver) {
this.siteRepository = siteRepository;
this.resolver = resolver;
}
public SitesChangedObservable getSitesChangedObservable() {
return sitesChangedObservable;
}
public boolean areSitesSetup() {
return !Sites.allSites().isEmpty();
return !siteRepository.all().getAll().isEmpty();
}
public void addSite(String url, SiteAddCallback callback) {
@ -87,14 +73,9 @@ public class SiteService {
return;
}
Site site = instantiateSiteClass(siteClass);
createNewSite(site);
loadSites();
Site site = siteRepository.createFromClass(siteClass);
callback.onSiteAdded(site);
sitesChangedObservable.doNotify();
}
public void updateUserSettings(Site site, JsonSettings jsonSettings) {
@ -103,22 +84,8 @@ public class SiteService {
siteRepository.updateSiteUserSettingsAsync(siteModel, jsonSettings);
}
public List<Site> getAllSitesInOrder() {
Map<Integer, Integer> ordering = siteRepository.getOrdering();
List<Site> all = Sites.allSites();
Site[] ordered = new Site[all.size()];
for (Site site : all) {
ordered[ordering.get(site.id())] = site;
}
return Arrays.asList(ordered);
}
public void updateOrdering(List<Site> sitesInNewOrder) {
siteRepository.updateSiteOrderingAsync(sitesInNewOrder,
() -> sitesChangedObservable.doNotify());
siteRepository.updateSiteOrderingAsync(sitesInNewOrder);
}
public void initialize() {
@ -129,79 +96,10 @@ public class SiteService {
if (addSiteForLegacy) {
addSiteForLegacy = false;
Site site = new Chan4();
SiteConfig config = new SiteConfig();
config.classId = SiteRegistry.SITE_CLASSES.indexOfValue(site.getClass());
config.external = false;
SiteModel model = siteRepository.create(config, new JsonSettings());
siteRepository.setId(model, 0);
}
loadSites();
}
private void loadSites() {
List<Site> sites = new ArrayList<>();
for (SiteModel siteModel : siteRepository.all()) {
sites.add(fromModel(siteModel));
siteRepository.addLegacySite();
}
Sites.initialize(sites);
for (Site site : sites) {
site.postInitialize();
}
}
/**
* Create a new site from the Site instance. This will insert the model for the site
* into the database and calls initialize on the site instance.
*
* @param site the site to add.
*/
private void createNewSite(Site site) {
SiteConfig config = new SiteConfig();
JsonSettings settings = new JsonSettings();
config.classId = SiteRegistry.SITE_CLASSES.indexOfValue(site.getClass());
config.external = false;
siteRepository.create(config, settings);
}
private Site fromModel(SiteModel siteModel) {
Pair<SiteConfig, JsonSettings> configFields = siteModel.loadConfigFields();
SiteConfig config = configFields.first;
JsonSettings settings = configFields.second;
Site site = instantiateSiteClass(config.classId);
site.initialize(siteModel.id, config, settings);
return site;
}
private Site instantiateSiteClass(int classId) {
Class<? extends Site> clazz = SiteRegistry.SITE_CLASSES.get(classId);
if (clazz == null) {
throw new IllegalArgumentException("Unknown class id");
}
return instantiateSiteClass(clazz);
}
private Site instantiateSiteClass(Class<? extends Site> clazz) {
Site site;
//noinspection TryWithIdenticalCatches
try {
site = clazz.newInstance();
} catch (InstantiationException e) {
throw new IllegalArgumentException();
} catch (IllegalAccessException e) {
throw new IllegalArgumentException();
}
return site;
siteRepository.initialize();
}
public interface SiteAddCallback {
@ -209,11 +107,4 @@ public class SiteService {
void onSiteAddFailed(String message);
}
public class SitesChangedObservable extends Observable {
private void doNotify() {
setChanged();
notifyObservers();
}
}
}

@ -1,35 +0,0 @@
package org.floens.chan.core.site;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Sites {
private static List<Site> ALL_SITES = Collections.unmodifiableList(new ArrayList<Site>());
/**
* Return all sites known in the system.
* <p>This list is immutable. Changes to the known sites cause this function to return a new immutable list
* with the site changes.
*
* @return list of sites known in the system.
*/
public static List<Site> allSites() {
return ALL_SITES;
}
public static Site forId(int id) {
// TODO: better datastructure
for (Site site : ALL_SITES) {
if (site.id() == id) {
return site;
}
}
return null;
}
static void initialize(List<Site> sites) {
Sites.ALL_SITES = Collections.unmodifiableList(new ArrayList<>(sites));
}
}

@ -44,9 +44,9 @@ import org.floens.chan.core.model.orm.Loadable;
import org.floens.chan.core.model.orm.Pin;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.core.site.Site;
import org.floens.chan.core.site.SiteService;
import org.floens.chan.core.repository.SiteRepository;
import org.floens.chan.core.site.SiteResolver;
import org.floens.chan.core.site.Sites;
import org.floens.chan.core.site.SiteService;
import org.floens.chan.ui.controller.BrowseController;
import org.floens.chan.ui.controller.DoubleNavigationController;
import org.floens.chan.ui.controller.DrawerController;
@ -228,7 +228,7 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat
}
private Loadable resolveLoadable(Loadable stateLoadable, boolean forThread) {
Site site = Sites.forId(stateLoadable.siteId);
Site site = SiteRepository.forId(stateLoadable.siteId);
if (site != null) {
Board board = site.board(stateLoadable.boardCode);
if (board != null) {

@ -22,6 +22,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.app.AlertDialog;
@ -38,6 +39,7 @@ import android.widget.TextView;
import org.floens.chan.R;
import org.floens.chan.core.presenter.SitesSetupPresenter;
import org.floens.chan.core.presenter.SitesSetupPresenter.SiteBoardCount;
import org.floens.chan.core.site.Site;
import org.floens.chan.core.site.SiteIcon;
import org.floens.chan.ui.helper.HintPopup;
@ -75,7 +77,7 @@ public class SitesSetupController extends StyledToolbarNavigationController impl
private SitesAdapter sitesAdapter;
private ItemTouchHelper itemTouchHelper;
private List<Site> sites = new ArrayList<>();
private List<SiteBoardCount> sites = new ArrayList<>();
private ItemTouchHelper.SimpleCallback touchHelperCallback = new ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP | ItemTouchHelper.DOWN,
@ -141,6 +143,13 @@ public class SitesSetupController extends StyledToolbarNavigationController impl
presenter.show();
}
@Override
public void onDestroy() {
super.onDestroy();
presenter.destroy();
}
public void showDoneCheckmark() {
navigation.swipeable = false;
navigation.menu = new ToolbarMenu(context);
@ -225,7 +234,7 @@ public class SitesSetupController extends StyledToolbarNavigationController impl
}
@Override
public void setAddedSites(List<Site> sites) {
public void setSites(List<SiteBoardCount> sites) {
this.sites.clear();
this.sites.addAll(sites);
sitesAdapter.notifyDataSetChanged();
@ -254,22 +263,23 @@ public class SitesSetupController extends StyledToolbarNavigationController impl
@Override
public long getItemId(int position) {
return sites.get(position).id();
return sites.get(position).site.id();
}
@NonNull
@Override
public SiteCell onCreateViewHolder(ViewGroup parent, int viewType) {
public SiteCell onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new SiteCell(LayoutInflater.from(context).inflate(R.layout.cell_site, parent, false));
}
@Override
public void onBindViewHolder(SiteCell holder, int position) {
Site site = sites.get(position);
holder.setSite(site);
holder.setSiteIcon(site);
holder.text.setText(site.name());
public void onBindViewHolder(@NonNull SiteCell holder, int position) {
SiteBoardCount site = sites.get(position);
holder.setSite(site.site);
holder.setSiteIcon(site.site);
holder.text.setText(site.site.name());
int boards = presenter.getSiteBoardCount(site);
int boards = site.boardCount;
String boardsString = context.getResources().getQuantityString(R.plurals.board, boards, boards);
String descriptionText = context.getString(R.string.setup_sites_site_description, boardsString);
holder.description.setText(descriptionText);

@ -31,7 +31,6 @@ import android.text.style.BackgroundColorSpan;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@ -46,7 +45,7 @@ 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.repository.BoardRepository;
import org.floens.chan.ui.controller.FiltersController;
import org.floens.chan.ui.dialog.ColorPickerView;
import org.floens.chan.ui.drawable.DropdownArrowDrawable;
@ -231,8 +230,8 @@ public class FilterLayout extends LinearLayout implements View.OnClickListener {
List<SelectLayout.SelectItem<Board>> items = new ArrayList<>();
List<Board> allSavedBoards = new ArrayList<>();
for (Pair<Site, List<Board>> sites : boardManager.getSavedBoardsObservable().get()) {
allSavedBoards.addAll(sites.second);
for (BoardRepository.SiteBoards item : boardManager.getSavedBoardsObservable().get()) {
allSavedBoards.addAll(item.boards);
}
for (Board board : allSavedBoards) {

Loading…
Cancel
Save