() {
@Override
public T call() {
diff --git a/Clover/app/src/main/java/org/floens/chan/core/di/AppModule.java b/Clover/app/src/main/java/org/floens/chan/core/di/AppModule.java
index 0531c588..9738082e 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/di/AppModule.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/di/AppModule.java
@@ -13,7 +13,8 @@ import org.floens.chan.core.database.DatabaseManager;
import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.manager.FilterEngine;
import org.floens.chan.core.manager.ReplyManager;
-import org.floens.chan.core.presenter.SetupPresenter;
+import org.floens.chan.core.presenter.BoardSetupPresenter;
+import org.floens.chan.core.presenter.SiteSetupPresenter;
import org.floens.chan.core.site.SiteManager;
import org.floens.chan.core.manager.WatchManager;
import org.floens.chan.core.net.BitmapLruImageCache;
@@ -24,12 +25,13 @@ import org.floens.chan.core.receiver.WatchUpdateReceiver;
import org.floens.chan.core.saver.ImageSaveTask;
import org.floens.chan.core.site.http.HttpCallManager;
import org.floens.chan.core.site.sites.chan4.Chan4;
-import org.floens.chan.core.site.sites.chan4.Chan4ReaderRequest;
+import org.floens.chan.core.site.common.ChanReaderRequest;
import org.floens.chan.core.update.UpdateManager;
import org.floens.chan.ui.activity.BoardActivity;
import org.floens.chan.ui.adapter.DrawerAdapter;
import org.floens.chan.ui.adapter.PostsFilter;
import org.floens.chan.ui.controller.BoardEditController;
+import org.floens.chan.ui.controller.BoardSetupController;
import org.floens.chan.ui.controller.BrowseController;
import org.floens.chan.ui.controller.DeveloperSettingsController;
import org.floens.chan.ui.controller.DrawerController;
@@ -38,6 +40,7 @@ import org.floens.chan.ui.controller.HistoryController;
import org.floens.chan.ui.controller.ImageViewerController;
import org.floens.chan.ui.controller.MainSettingsController;
import org.floens.chan.ui.controller.PassSettingsController;
+import org.floens.chan.ui.controller.SiteSetupController;
import org.floens.chan.ui.controller.ViewThreadController;
import org.floens.chan.ui.helper.ImagePickDelegate;
import org.floens.chan.ui.layout.FilterLayout;
@@ -65,7 +68,7 @@ import dagger.Provides;
ChanApplication.class,
MainSettingsController.class,
ReplyPresenter.class,
- Chan4ReaderRequest.class,
+ ChanReaderRequest.class,
ThreadLayout.class,
DeveloperSettingsController.class,
BoardActivity.class,
@@ -92,7 +95,10 @@ import dagger.Provides;
WatchManager.PinWatcher.class,
UpdateManager.class,
SiteManager.class,
- SetupPresenter.class,
+ SiteSetupPresenter.class,
+ BoardSetupPresenter.class,
+ SiteSetupController.class,
+ BoardSetupController.class,
Chan4.class,
},
diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java
index c0ed715c..270afbde 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java
@@ -22,13 +22,11 @@ import org.floens.chan.core.model.orm.Board;
import org.floens.chan.core.site.Boards;
import org.floens.chan.core.site.Site;
import org.floens.chan.core.site.Sites;
+import org.floens.chan.utils.Logger;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -36,7 +34,15 @@ import javax.inject.Singleton;
import de.greenrobot.event.EventBus;
/**
- * Keeps track of {@link Board}s that the user has "saved" to their list.
+ * Keeps track of {@link Board}s in the system.
+ *
There are a few types of sites, those who provide a list of all boards known,
+ * sites where users can create boards and have a very long list of known boards,
+ * and those who don't provide a board list at all.
+ *
We try to save as much info about boards as possible, this means that we try to save all
+ * boards we encounter.
+ * For sites with a small list of boards which does provide a board list api we save all those boards.
+ *
All boards have a {@link Board#saved} flag indicating if it should be visible in the user's
+ * favorite board list, along with a {@link Board#order} in which they appear.
*/
@Singleton
public class BoardManager {
@@ -57,24 +63,66 @@ public class BoardManager {
};
private final DatabaseManager databaseManager;
- private final Site defaultSite;
- private final List boards;
private final List savedBoards = new ArrayList<>();
- private final Map boardsByCode = new HashMap<>();
@Inject
public BoardManager(DatabaseManager databaseManager) {
this.databaseManager = databaseManager;
- defaultSite = Sites.defaultSite();
- boards = databaseManager.runTaskSync(databaseManager.getDatabaseBoardManager().getBoards(defaultSite));
- if (boards.isEmpty()) {
- update(false);
+ loadBoards();
+
+ fetchLimitedSitesTheirBoards();
+ }
+
+ public List getSavedBoards() {
+ return savedBoards;
+ }
+
+ public void saveBoard(Board board) {
+ board.saved = true;
+
+ board = databaseManager.runTaskSync(databaseManager.getDatabaseBoardManager().createOrUpdate(board));
+
+ loadBoards();
+ }
+
+ public void unsaveBoard(Board board) {
+ board.saved = false;
+
+ board = databaseManager.runTaskSync(databaseManager.getDatabaseBoardManager().createOrUpdate(board));
+
+ loadBoards();
+ }
+
+ private void loadBoards() {
+ savedBoards.clear();
+ savedBoards.addAll(databaseManager.runTaskSync(databaseManager.getDatabaseBoardManager().getSavedBoards()));
+
+ EventBus.getDefault().post(new BoardsChangedMessage());
+ }
+
+ private void fetchLimitedSitesTheirBoards() {
+ List sites = Sites.allSites();
+ for (final Site site : sites) {
+ if (site.boardsType() == Site.BoardsType.DYNAMIC) {
+ site.boards(new Site.BoardsListener() {
+ @Override
+ public void onBoardsReceived(Boards boards) {
+ handleBoardsFetch(site, boards);
+ }
+ });
+ }
}
}
- private void appendBoards(Boards response) {
+ private void handleBoardsFetch(Site site, Boards boards) {
+ Logger.i(TAG, "Got boards for " + site.name());
+
+ databaseManager.runTask(databaseManager.getDatabaseBoardManager().createAll(boards.boards));
+ }
+
+ /*private void appendBoards(Boards response) {
List boardsToAddWs = new ArrayList<>();
List boardsToAddNws = new ArrayList<>();
@@ -131,9 +179,9 @@ public class BoardManager {
public void flushOrderAndSaved() {
saveDatabase();
update(true);
- }
+ }*/
- private void update(boolean notify) {
+ /*private void update(boolean notify) {
savedBoards.clear();
savedBoards.addAll(filterSaved(boards));
synchronized (boardsByCode) {
@@ -145,13 +193,13 @@ public class BoardManager {
if (notify) {
EventBus.getDefault().post(new BoardsChangedMessage());
}
- }
+ }*/
- private void saveDatabase() {
+ /*private void saveDatabase() {
databaseManager.runTask(databaseManager.getDatabaseBoardManager().setBoards(boards));
- }
+ }*/
- private List filterSaved(List all) {
+ /*private List filterSaved(List all) {
List saved = new ArrayList<>(all.size());
for (int i = 0; i < all.size(); i++) {
Board board = all.get(i);
@@ -161,7 +209,7 @@ public class BoardManager {
}
Collections.sort(saved, ORDER_SORT);
return saved;
- }
+ }*/
public static class BoardsChangedMessage {
}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/orm/Board.java b/Clover/app/src/main/java/org/floens/chan/core/model/orm/Board.java
index 21f8ac73..d21a9ffe 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/model/orm/Board.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/model/orm/Board.java
@@ -27,18 +27,6 @@ import org.floens.chan.core.site.Site;
@DatabaseTable(tableName = "board")
public class Board implements SiteReference {
- public Board() {
- }
-
- public Board(Site site, String name, String code, boolean saved, boolean workSafe) {
- this.siteId = site.id();
- this.site = site;
- this.name = name;
- this.code = code;
- this.saved = saved;
- this.workSafe = workSafe;
- }
-
@DatabaseField(generatedId = true)
public int id;
@@ -50,9 +38,6 @@ public class Board implements SiteReference {
*/
public transient Site site;
- /**
- * {@code true} if this board appears in the dropdown, {@code false} otherwise.
- */
@DatabaseField
public boolean saved = false;
@@ -62,12 +47,10 @@ public class Board implements SiteReference {
@DatabaseField
public int order;
- // named key for legacy support
- @DatabaseField(columnName = "key")
+ @DatabaseField(columnName = "key") // named key for legacy support
public String name;
- // named value for legacy support
- @DatabaseField(columnName = "value")
+ @DatabaseField(columnName = "value") // named value for legacy support
// TODO(sec) force filter this to ascii & numbers.
public String code;
@@ -142,6 +125,29 @@ public class Board implements SiteReference {
@DatabaseField
public String description;
+ @Deprecated // public, at least
+ public Board() {
+ }
+
+ @Deprecated
+ public Board(Site site, String name, String code, boolean saved, boolean workSafe) {
+ this.siteId = site.id();
+ this.site = site;
+ this.name = name;
+ this.code = code;
+ this.saved = saved;
+ this.workSafe = workSafe;
+ }
+
+ public static Board fromSiteNameCode(Site site, String name, String code) {
+ Board board = new Board();
+ board.siteId = site.id();
+ board.site = site;
+ board.name = name;
+ board.code = code;
+ return board;
+ }
+
public boolean finish() {
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(code) || perPage < 0 || pages < 0) {
return false;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/BoardSetupPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/BoardSetupPresenter.java
new file mode 100644
index 00000000..ff851a7a
--- /dev/null
+++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/BoardSetupPresenter.java
@@ -0,0 +1,109 @@
+/*
+ * 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 .
+ */
+package org.floens.chan.core.presenter;
+
+
+import org.floens.chan.core.manager.BoardManager;
+import org.floens.chan.core.model.orm.Board;
+import org.floens.chan.core.site.Site;
+import org.floens.chan.core.site.Sites;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import static org.floens.chan.Chan.getGraph;
+
+public class BoardSetupPresenter {
+ private Callback callback;
+
+ private final List sites = new ArrayList<>();
+
+ @Inject
+ BoardManager boardManager;
+
+ private List savedBoards;
+
+ @Inject
+ public BoardSetupPresenter() {
+ getGraph().inject(this);
+ }
+
+ public void create(Callback callback) {
+ this.callback = callback;
+
+ sites.addAll(Sites.allSites());
+
+ loadSavedBoards();
+ callback.setSavedBoards(savedBoards);
+ }
+
+ public void addFromSuggestion(BoardSuggestion suggestion) {
+ Board board = Board.fromSiteNameCode(suggestion.site, suggestion.key, suggestion.key);
+
+ boardManager.saveBoard(board);
+
+ loadSavedBoards();
+ callback.setSavedBoards(savedBoards);
+ }
+
+ public void move(int from, int to) {
+ Board item = savedBoards.remove(from);
+ savedBoards.add(to, item);
+
+ callback.setSavedBoards(savedBoards);
+ }
+
+ public void remove(int position) {
+ Board board = savedBoards.remove(position);
+
+ boardManager.unsaveBoard(board);
+
+ loadSavedBoards();
+ callback.setSavedBoards(savedBoards);
+ }
+
+ public List getSuggestionsForQuery(String query) {
+ List suggestions = new ArrayList<>();
+
+ for (Site site : sites) {
+ suggestions.add(new BoardSuggestion(query, site));
+ }
+
+ return suggestions;
+ }
+
+ private void loadSavedBoards() {
+ savedBoards = new ArrayList<>(boardManager.getSavedBoards());
+ }
+
+ public interface Callback {
+ void setSavedBoards(List savedBoards);
+ }
+
+ public static class BoardSuggestion {
+ public final String key;
+ public final Site site;
+
+ public BoardSuggestion(String key, Site site) {
+ this.key = key;
+ this.site = site;
+ }
+ }
+}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/SetupPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/SiteSetupPresenter.java
similarity index 94%
rename from Clover/app/src/main/java/org/floens/chan/core/presenter/SetupPresenter.java
rename to Clover/app/src/main/java/org/floens/chan/core/presenter/SiteSetupPresenter.java
index ae8edb6d..cec53648 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/presenter/SetupPresenter.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/SiteSetupPresenter.java
@@ -29,7 +29,7 @@ import javax.inject.Inject;
import static org.floens.chan.Chan.getGraph;
-public class SetupPresenter {
+public class SiteSetupPresenter {
@Inject
SiteManager siteManager;
@@ -38,14 +38,14 @@ public class SetupPresenter {
private List sites = new ArrayList<>();
@Inject
- public SetupPresenter() {
+ public SiteSetupPresenter() {
getGraph().inject(this);
}
public void create(Callback callback) {
this.callback = callback;
- sites.addAll(Sites.ALL_SITES);
+ sites.addAll(Sites.allSites());
this.callback.setAddedSites(sites);
@@ -80,7 +80,7 @@ public class SetupPresenter {
private void siteAdded(Site site) {
sites.clear();
- sites.addAll(Sites.ALL_SITES);
+ sites.addAll(Sites.allSites());
callback.setAddedSites(sites);
callback.runSiteAddedAnimation(site);
diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/Site.java b/Clover/app/src/main/java/org/floens/chan/core/site/Site.java
index 991bd7d3..074cd8dc 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/site/Site.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/site/Site.java
@@ -88,7 +88,7 @@ public interface Site {
*/
enum BoardsType {
/**
- * The site's boards are static, hard-coded in the site.
+ * The site's boards are static, there is no extra info for a board in the api.
*/
STATIC,
diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteIcon.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteIcon.java
index d6f8547b..f375aa25 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/site/SiteIcon.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteIcon.java
@@ -46,6 +46,9 @@ public class SiteIcon {
return siteIcon;
}
+ private SiteIcon() {
+ }
+
public void get(SiteIconResult result) {
if (assetPath != null) {
Bitmap bitmap;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java
index 6cba35e4..7a9b2f61 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java
@@ -51,9 +51,9 @@ public class SiteManager {
public void addSite(String url, SiteAddCallback callback) {
SiteResolver.SiteResolverResult resolve = resolver.resolve(url);
- Site site;
+ Class extends Site> siteClass;
if (resolve.match == SiteResolver.SiteResolverResult.Match.BUILTIN) {
- site = instantiateSiteClass(resolve.builtinResult);
+ siteClass = resolve.builtinResult;
} else if (resolve.match == SiteResolver.SiteResolverResult.Match.EXTERNAL) {
callback.onSiteAddFailed("external todo");
return;
@@ -62,11 +62,16 @@ public class SiteManager {
return;
}
+ addSiteFromClass(siteClass, callback);
+ }
+
+ public void addSiteFromClass(Class extends Site> siteClass, SiteAddCallback callback) {
+ Site site = instantiateSiteClass(siteClass);
site = createNewSite(site);
- List newAllSites = new ArrayList<>(Sites.ALL_SITES);
+ List newAllSites = new ArrayList<>(Sites.allSites());
newAllSites.add(site);
- Sites.initialize(newAllSites);
+ setAvailableSites(newAllSites);
callback.onSiteAdded(site);
}
@@ -91,7 +96,11 @@ public class SiteManager {
sites.add(site);
}
- Sites.initialize(sites);
+ setAvailableSites(sites);
+ }
+
+ private void setAvailableSites(List newAllSites) {
+ Sites.initialize(newAllSites);
}
private List loadSitesFromDatabase() {
diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/Sites.java b/Clover/app/src/main/java/org/floens/chan/core/site/Sites.java
index b816b908..673d6b9c 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/site/Sites.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/site/Sites.java
@@ -3,8 +3,10 @@ package org.floens.chan.core.site;
import android.util.SparseArray;
import org.floens.chan.core.site.sites.chan4.Chan4;
+import org.floens.chan.core.site.sites.chan8.Chan8;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class Sites {
@@ -15,15 +17,28 @@ public class Sites {
// This differs from the Site.id() id, that id is used for site instance linking, this is just to
// find the correct class to use.
SITE_CLASSES.put(0, Chan4.class);
+
+ SITE_CLASSES.put(1, Chan8.class);
}
public static final List RESOLVABLES = new ArrayList<>();
static {
RESOLVABLES.add(Chan4.RESOLVABLE);
+ RESOLVABLES.add(Chan8.RESOLVABLE);
}
- public static final List ALL_SITES = new ArrayList<>();
+ private static List ALL_SITES = Collections.unmodifiableList(new ArrayList());
+
+ /**
+ * Return all sites known in the system.
+ * 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 allSites() {
+ return ALL_SITES;
+ }
@Deprecated
private static Site defaultSite;
@@ -46,7 +61,6 @@ public class Sites {
static void initialize(List sites) {
Sites.defaultSite = sites.isEmpty() ? null : sites.get(0);
- Sites.ALL_SITES.clear();
- Sites.ALL_SITES.addAll(sites);
+ Sites.ALL_SITES = Collections.unmodifiableList(new ArrayList<>(sites));
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReaderRequest.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java
similarity index 97%
rename from Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReaderRequest.java
rename to Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java
index e7888062..700ce062 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReaderRequest.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package org.floens.chan.core.site.sites.chan4;
+package org.floens.chan.core.site.common;
import android.util.JsonReader;
@@ -56,8 +56,8 @@ import static org.floens.chan.Chan.getGraph;
* This class is highly multithreaded, take good care to not access models that are to be only
* changed on the main thread.
*/
-public class Chan4ReaderRequest extends JsonReaderRequest {
- private static final String TAG = "Chan4ReaderRequest";
+public class ChanReaderRequest extends JsonReaderRequest {
+ private static final String TAG = "ChanReaderRequest";
private static final boolean LOG_TIMING = false;
private static final int THREAD_COUNT;
@@ -85,7 +85,7 @@ public class Chan4ReaderRequest extends JsonReaderRequest {
private List filters;
private long startLoad;
- public Chan4ReaderRequest(ChanLoaderRequestParams request) {
+ public ChanReaderRequest(ChanLoaderRequestParams request) {
super(getChanUrl(request.loadable).toString(), request.listener, request.errorListener);
getGraph().inject(this);
@@ -360,7 +360,7 @@ public class Chan4ReaderRequest extends JsonReaderRequest {
builder.board(loadable.board);
// File
- long fileId = 0;
+ String fileId = null;
String fileExt = null;
int fileWidth = 0;
int fileHeight = 0;
@@ -397,7 +397,7 @@ public class Chan4ReaderRequest extends JsonReaderRequest {
builder.comment(reader.nextString());
break;
case "tim":
- fileId = reader.nextLong();
+ fileId = reader.nextString();
break;
case "time":
builder.setUnixTimestampSeconds(reader.nextLong());
@@ -491,9 +491,9 @@ public class Chan4ReaderRequest extends JsonReaderRequest {
}
SiteEndpoints endpoints = loadable.getSite().endpoints();
- if (fileId != 0 && fileName != null && fileExt != null) {
+ if (fileId != null && fileName != null && fileExt != null) {
Map hack = new HashMap<>(2);
- hack.put("tim", String.valueOf(fileId));
+ hack.put("tim", fileId);
hack.put("ext", fileExt);
builder.image(new PostImage.Builder()
.originalName(String.valueOf(fileId))
diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/PostParseCallable.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/PostParseCallable.java
similarity index 97%
rename from Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/PostParseCallable.java
rename to Clover/app/src/main/java/org/floens/chan/core/site/common/PostParseCallable.java
index c8df3f26..ebc851c8 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/PostParseCallable.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/PostParseCallable.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package org.floens.chan.core.site.sites.chan4;
+package org.floens.chan.core.site.common;
import org.floens.chan.chan.ChanParser;
import org.floens.chan.core.database.DatabaseSavedReplyManager;
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.concurrent.Callable;
// Called concurrently to parse the post html and the filters on it
+// Belongs to ChanReaderRequest
class PostParseCallable implements Callable {
private static final String TAG = "PostParseCallable";
diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java
index e53ab491..2454c917 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java
@@ -41,6 +41,7 @@ import org.floens.chan.core.site.SiteBase;
import org.floens.chan.core.site.SiteEndpoints;
import org.floens.chan.core.site.SiteIcon;
import org.floens.chan.core.site.SiteRequestModifier;
+import org.floens.chan.core.site.common.ChanReaderRequest;
import org.floens.chan.core.site.http.DeleteRequest;
import org.floens.chan.core.site.http.HttpCall;
import org.floens.chan.core.site.http.HttpCallManager;
@@ -376,7 +377,7 @@ public class Chan4 extends SiteBase {
@Override
public Board board(String code) {
- List allBoards = getGraph().get(BoardManager.class).getAllBoards();
+ List allBoards = getGraph().get(BoardManager.class).getSavedBoards();
for (Board board : allBoards) {
if (board.code.equals(code)) {
return board;
@@ -403,7 +404,7 @@ public class Chan4 extends SiteBase {
@Override
public ChanLoaderRequest loaderRequest(ChanLoaderRequestParams request) {
- return new ChanLoaderRequest(new Chan4ReaderRequest(request));
+ return new ChanLoaderRequest(new ChanReaderRequest(request));
}
@Override
diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java
new file mode 100644
index 00000000..0ea11daa
--- /dev/null
+++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java
@@ -0,0 +1,254 @@
+/*
+ * 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 .
+ */
+package org.floens.chan.core.site.sites.chan8;
+
+
+import android.support.annotation.Nullable;
+import android.webkit.WebView;
+
+import org.floens.chan.chan.ChanLoaderRequest;
+import org.floens.chan.chan.ChanLoaderRequestParams;
+import org.floens.chan.core.model.Post;
+import org.floens.chan.core.model.orm.Board;
+import org.floens.chan.core.model.orm.Loadable;
+import org.floens.chan.core.site.Resolvable;
+import org.floens.chan.core.site.Site;
+import org.floens.chan.core.site.SiteAuthentication;
+import org.floens.chan.core.site.SiteBase;
+import org.floens.chan.core.site.SiteEndpoints;
+import org.floens.chan.core.site.SiteIcon;
+import org.floens.chan.core.site.SiteRequestModifier;
+import org.floens.chan.core.site.common.ChanReaderRequest;
+import org.floens.chan.core.site.http.DeleteRequest;
+import org.floens.chan.core.site.http.HttpCall;
+import org.floens.chan.core.site.http.LoginRequest;
+import org.floens.chan.core.site.http.Reply;
+
+import java.util.Locale;
+import java.util.Map;
+
+import okhttp3.HttpUrl;
+import okhttp3.Request;
+
+public class Chan8 extends SiteBase {
+ public static final Resolvable RESOLVABLE = new Resolvable() {
+ @Override
+ public ResolveResult resolve(String value) {
+ if (value.equals("8chan")) {
+ return ResolveResult.NAME_MATCH;
+ } else if (value.equals("https://8ch.net/")) {
+ return ResolveResult.FULL_MATCH;
+ } else {
+ return ResolveResult.NO;
+ }
+ }
+
+ @Override
+ public Class extends Site> getSiteClass() {
+ return Chan8.class;
+ }
+ };
+
+ private final SiteEndpoints endpoints = new SiteEndpoints() {
+ private final HttpUrl root = new HttpUrl.Builder()
+ .scheme("https")
+ .host("8ch.net")
+ .build();
+
+ private final HttpUrl media = new HttpUrl.Builder()
+ .scheme("https")
+ .host("media.8ch.net")
+ .build();
+
+ @Override
+ public HttpUrl catalog(Board board) {
+ return root.newBuilder()
+ .addPathSegment(board.code)
+ .addPathSegment("catalog.json")
+ .build();
+ }
+
+ @Override
+ public HttpUrl thread(Board board, Loadable loadable) {
+ return root.newBuilder()
+ .addPathSegment(board.code)
+ .addPathSegment("res")
+ .addPathSegment(loadable.no + ".json")
+ .build();
+ }
+
+ @Override
+ public HttpUrl imageUrl(Post.Builder post, Map arg) {
+ return root.newBuilder()
+ .addPathSegment("file_store")
+ .addPathSegment(arg.get("tim") + "." + arg.get("ext"))
+ .build();
+ }
+
+ @Override
+ public HttpUrl thumbnailUrl(Post.Builder post, boolean spoiler, Map arg) {
+ return root.newBuilder()
+ .addPathSegment("file_store")
+ .addPathSegment("thumb")
+ .addPathSegment(arg.get("tim") + "." + arg.get("ext"))
+ .build();
+ }
+
+ @Override
+ public HttpUrl icon(Post.Builder post, String icon, Map arg) {
+ HttpUrl.Builder stat = root.newBuilder().addPathSegment("static");
+
+ switch (icon) {
+ case "country":
+ stat.addPathSegment("flags");
+ stat.addPathSegment(arg.get("country_code").toLowerCase(Locale.ENGLISH) + ".png");
+ break;
+ }
+
+ return stat.build();
+ }
+
+ @Override
+ public HttpUrl boards() {
+ return null;
+ }
+
+ @Override
+ public HttpUrl reply(Loadable loadable) {
+ return null;
+ }
+
+ @Override
+ public HttpUrl delete(Post post) {
+ return null;
+ }
+
+ @Override
+ public HttpUrl report(Post post) {
+ return null;
+ }
+
+ @Override
+ public HttpUrl login() {
+ return null;
+ }
+ };
+
+ private SiteRequestModifier siteRequestModifier = new SiteRequestModifier() {
+ @Override
+ public void modifyHttpCall(HttpCall httpCall, Request.Builder requestBuilder) {
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void modifyWebView(WebView webView) {
+ }
+ };
+
+ private SiteAuthentication authentication = new SiteAuthentication() {
+ @Override
+ public boolean requireAuthentication(AuthenticationRequestType type) {
+ return false;
+ }
+ };
+
+ @Override
+ public String name() {
+ return "8chan";
+ }
+
+ @Override
+ public SiteIcon icon() {
+ return SiteIcon.fromAssets("icons/8chan.png");
+ }
+
+ @Override
+ public boolean feature(Feature feature) {
+ return false;
+ }
+
+ @Override
+ public boolean boardFeature(BoardFeature boardFeature, Board board) {
+ return false;
+ }
+
+ @Override
+ public SiteEndpoints endpoints() {
+ return endpoints;
+ }
+
+ @Override
+ public SiteRequestModifier requestModifier() {
+ return siteRequestModifier;
+ }
+
+ @Override
+ public SiteAuthentication authentication() {
+ return authentication;
+ }
+
+ @Override
+ public BoardsType boardsType() {
+ return BoardsType.INFINITE;
+ }
+
+ @Override
+ public String desktopUrl(Loadable loadable, @Nullable Post post) {
+ return "https://8ch.net/";
+ }
+
+ @Override
+ public void boards(BoardsListener boardsListener) {
+ }
+
+ @Override
+ public Board board(String code) {
+ return null;
+ }
+
+ @Override
+ public ChanLoaderRequest loaderRequest(ChanLoaderRequestParams request) {
+ return new ChanLoaderRequest(new ChanReaderRequest(request));
+ }
+
+ @Override
+ public void post(Reply reply, PostListener postListener) {
+ }
+
+ @Override
+ public void delete(DeleteRequest deleteRequest, DeleteListener deleteListener) {
+ }
+
+ @Override
+ public void login(LoginRequest loginRequest, LoginListener loginListener) {
+ }
+
+ @Override
+ public void logout() {
+ }
+
+ @Override
+ public boolean isLoggedIn() {
+ return false;
+ }
+
+ @Override
+ public LoginRequest getLoginDetails() {
+ return null;
+ }
+}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardEditController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardEditController.java
index e4a035b2..c0f3ed90 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardEditController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardEditController.java
@@ -44,7 +44,6 @@ import org.floens.chan.R;
import org.floens.chan.controller.Controller;
import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.model.orm.Board;
-import org.floens.chan.ui.drawable.ThumbDrawable;
import org.floens.chan.ui.helper.BoardHelper;
import org.floens.chan.ui.toolbar.ToolbarMenu;
import org.floens.chan.ui.toolbar.ToolbarMenuItem;
@@ -182,7 +181,8 @@ public class BoardEditController extends Controller implements View.OnClickListe
boards.get(i).order = i;
}
- boardManager.flushOrderAndSaved();
+ // TODO(multisite)
+// boardManager.flushOrderAndSaved();
}
@Override
@@ -243,7 +243,7 @@ public class BoardEditController extends Controller implements View.OnClickListe
}
// Normal add
- List all = boardManager.getAllBoards();
+ List all = boardManager.getSavedBoards();
for (Board board : all) {
if (board.code.equals(value)) {
board.saved = true;
@@ -385,7 +385,7 @@ public class BoardEditController extends Controller implements View.OnClickListe
}
}*/
List s = new ArrayList<>();
- for (Board b : boardManager.getAllBoards()) {
+ for (Board b : boardManager.getSavedBoards()) {
if (!haveBoard(b.code)/* && (showUnsafe || b.workSafe)*/) {
s.add(b);
}
@@ -454,7 +454,6 @@ public class BoardEditController extends Controller implements View.OnClickListe
thumb = (ImageView) itemView.findViewById(R.id.thumb);
text = (TextView) itemView.findViewById(R.id.text);
description = (TextView) itemView.findViewById(R.id.description);
- thumb.setImageDrawable(new ThumbDrawable());
thumb.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardSetupController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardSetupController.java
index 6cc1d080..6e92acf2 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardSetupController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardSetupController.java
@@ -19,34 +19,49 @@ package org.floens.chan.ui.controller;
import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
+import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
+import android.widget.BaseAdapter;
+import android.widget.Filter;
+import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
+import org.floens.chan.core.model.orm.Board;
+import org.floens.chan.core.presenter.BoardSetupPresenter;
+import org.floens.chan.core.site.SiteIcon;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import static org.floens.chan.utils.AndroidUtils.getAppContext;
-import static org.floens.chan.utils.AndroidUtils.getRes;
+import javax.inject.Inject;
+
+import static org.floens.chan.Chan.getGraph;
+import static org.floens.chan.ui.helper.PostHelper.formatBoardCodeAndName;
+import static org.floens.chan.utils.AndroidUtils.getAttrColor;
+
+public class BoardSetupController extends Controller implements View.OnClickListener, AdapterView.OnItemClickListener, BoardSetupPresenter.Callback {
+ @Inject
+ BoardSetupPresenter presenter;
-public class BoardSetupController extends Controller implements View.OnClickListener {
private AutoCompleteTextView code;
private RecyclerView savedBoardsRecycler;
- private SavedBoardsAdapter adapter;
+ private SuggestBoardsAdapter suggestAdapter;
+
+ private SavedBoardsAdapter savedAdapter;
+ private ItemTouchHelper itemTouchHelper;
public BoardSetupController(Context context) {
super(context);
@@ -56,71 +71,146 @@ public class BoardSetupController extends Controller implements View.OnClickList
public void onCreate() {
super.onCreate();
+ getGraph().inject(this);
+
view = inflateRes(R.layout.controller_board_setup);
navigationItem.setTitle(R.string.saved_boards_title);
+ navigationItem.swipeable = false;
code = (AutoCompleteTextView) view.findViewById(R.id.code);
+ code.setOnItemClickListener(this);
savedBoardsRecycler = (RecyclerView) view.findViewById(R.id.boards_recycler);
savedBoardsRecycler.setLayoutManager(new LinearLayoutManager(context));
- adapter = new SavedBoardsAdapter();
- savedBoardsRecycler.setAdapter(adapter);
-
- List savedBoards = new ArrayList<>();
- for (int board = 0; board < 5; board++) {
- savedBoards.add(new SavedBoard("foo - " + board, board));
- }
-
- adapter.setSavedBoards(savedBoards);
-
- List foo = new ArrayList() {{
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("foo");
- add("bar");
- add("baz");
- }};
-
- ArrayAdapter adapter = new ArrayAdapter<>(context, android.R.layout.simple_dropdown_item_1line, foo);
- code.setAdapter(adapter);
+ savedAdapter = new SavedBoardsAdapter();
+ savedBoardsRecycler.setAdapter(savedAdapter);
+
+ itemTouchHelper = new ItemTouchHelper(touchHelperCallback);
+ itemTouchHelper.attachToRecyclerView(savedBoardsRecycler);
+
+ suggestAdapter = new SuggestBoardsAdapter();
+
+ code.setAdapter(suggestAdapter);
code.setThreshold(1);
+
+ presenter.create(this);
+ }
+
+ private ItemTouchHelper.SimpleCallback touchHelperCallback = new ItemTouchHelper.SimpleCallback(
+ ItemTouchHelper.UP | ItemTouchHelper.DOWN,
+ ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT
+ ) {
+ @Override
+ public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
+ int from = viewHolder.getAdapterPosition();
+ int to = target.getAdapterPosition();
+
+ presenter.move(from, to);
+
+ return true;
+ }
+
+ @Override
+ public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
+ int position = viewHolder.getAdapterPosition();
+
+ presenter.remove(position);
+ }
+ };
+
+ @Override
+ public void setSavedBoards(List savedBoards) {
+ savedAdapter.setSavedBoards(savedBoards);
}
@Override
public void onClick(View v) {
}
- private class SavedBoard {
- private String title;
- private int id;
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ BoardSetupPresenter.BoardSuggestion suggestion = suggestAdapter.getSuggestion(position);
+
+ presenter.addFromSuggestion(suggestion);
+ }
+
+ private class SuggestBoardsAdapter extends BaseAdapter implements Filterable {
+ private List suggestions = new ArrayList<>();
- public SavedBoard(String title, int id) {
- this.title = title;
- this.id = id;
+ @Override
+ public int getCount() {
+ return suggestions.size();
+ }
+
+ @Override
+ public String getItem(int position) {
+ return getSuggestion(position).key;
+ }
+
+ public BoardSetupPresenter.BoardSuggestion getSuggestion(int position) {
+ return suggestions.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view = LayoutInflater.from(context).inflate(R.layout.cell_board_suggestion, parent, false);
+
+ final ImageView image = (ImageView) view.findViewById(R.id.image);
+ TextView text = (TextView) view.findViewById(R.id.text);
+
+ BoardSetupPresenter.BoardSuggestion suggestion = getSuggestion(position);
+
+ final SiteIcon icon = suggestion.site.icon();
+ icon.get(new SiteIcon.SiteIconResult() {
+ @Override
+ public void onSiteIcon(SiteIcon siteIcon, Drawable icon) {
+ // TODO: don't if recycled
+ image.setImageDrawable(icon);
+ }
+ });
+
+ text.setText(suggestion.site.name() + " \u2013 /" + suggestion.key + "/");
+
+ return view;
+ }
+
+ @Override
+ public Filter getFilter() {
+ return new Filter() {
+ @Override
+ protected FilterResults performFiltering(CharSequence constraint) {
+ // Invoked on a worker thread, do not use.
+ return null;
+ }
+
+ @Override
+ protected void publishResults(CharSequence constraint, FilterResults results) {
+ suggestions.clear();
+
+ if (constraint != null) {
+ suggestions.addAll(presenter.getSuggestionsForQuery(constraint.toString()));
+ }
+
+ notifyDataSetChanged();
+ }
+ };
}
}
private class SavedBoardsAdapter extends RecyclerView.Adapter {
- private List savedBoards = new ArrayList<>();
+ private List savedBoards;
public SavedBoardsAdapter() {
setHasStableIds(true);
}
- private void setSavedBoards(List savedBoards) {
- this.savedBoards.clear();
- this.savedBoards.addAll(savedBoards);
+ private void setSavedBoards(List savedBoards) {
+ this.savedBoards = savedBoards;
notifyDataSetChanged();
}
@@ -136,7 +226,7 @@ public class BoardSetupController extends Controller implements View.OnClickList
@Override
public void onBindViewHolder(SavedBoardCell holder, int position) {
- SavedBoard savedBoard = savedBoards.get(position);
+ Board savedBoard = savedBoards.get(position);
holder.setSavedBoard(savedBoard);
}
@@ -149,30 +239,43 @@ public class BoardSetupController extends Controller implements View.OnClickList
private class SavedBoardCell extends RecyclerView.ViewHolder {
private ImageView image;
private TextView text;
+ private SiteIcon siteIcon;
+ private ImageView reorder;
public SavedBoardCell(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
text = (TextView) itemView.findViewById(R.id.text);
+ reorder = (ImageView) itemView.findViewById(R.id.reorder);
+
+ Drawable drawable = DrawableCompat.wrap(context.getResources().getDrawable(R.drawable.ic_reorder_black_24dp)).mutate();
+ DrawableCompat.setTint(drawable, getAttrColor(context, R.attr.text_color_hint));
+ reorder.setImageDrawable(drawable);
+
+ reorder.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ itemTouchHelper.startDrag(SavedBoardCell.this);
+ }
+ return false;
+ }
+ });
}
- public void setSavedBoard(SavedBoard savedBoard) {
- Bitmap bitmap;
- try {
- BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inScaled = false;
- bitmap = BitmapFactory.decodeStream(getAppContext().getAssets().open("icons/4chan.png"), null, opts);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- BitmapDrawable drawable = new BitmapDrawable(getRes(), bitmap);
- drawable = (BitmapDrawable) drawable.mutate();
- drawable.getPaint().setFilterBitmap(false);
-
- image.setImageDrawable(drawable);
- text.setText(savedBoard.title);
+ public void setSavedBoard(Board savedBoard) {
+ siteIcon = savedBoard.site.icon();
+ siteIcon.get(new SiteIcon.SiteIconResult() {
+ @Override
+ public void onSiteIcon(SiteIcon siteIcon, Drawable icon) {
+ if (SavedBoardCell.this.siteIcon == siteIcon) {
+ image.setImageDrawable(icon);
+ }
+ }
+ });
+
+ text.setText(formatBoardCodeAndName(savedBoard));
}
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java
index 06b5c6b6..e75204ff 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java
@@ -30,6 +30,7 @@ import android.widget.TextView;
import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls;
+import org.floens.chan.controller.Controller;
import org.floens.chan.core.database.DatabaseManager;
import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.model.orm.Board;
@@ -235,7 +236,7 @@ public class BrowseController extends ThreadController implements ToolbarMenuIte
if (item instanceof FloatingMenuItemBoard) {
loadBoard(((FloatingMenuItemBoard) item).board);
} else {
- BoardEditController boardEditController = new BoardEditController(context);
+ Controller boardEditController = new BoardSetupController(context);
if (doubleNavigationController != null) {
doubleNavigationController.pushController(boardEditController);
} else {
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/SiteSetupController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/SiteSetupController.java
index 3cc1d5ec..a1807457 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/SiteSetupController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/SiteSetupController.java
@@ -45,7 +45,7 @@ import android.widget.TextView;
import org.floens.chan.R;
import org.floens.chan.controller.transition.FadeInTransition;
-import org.floens.chan.core.presenter.SetupPresenter;
+import org.floens.chan.core.presenter.SiteSetupPresenter;
import org.floens.chan.core.site.Site;
import org.floens.chan.core.site.SiteIcon;
import org.floens.chan.ui.animation.AnimationUtils;
@@ -53,10 +53,16 @@ import org.floens.chan.ui.animation.AnimationUtils;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+
+import static org.floens.chan.Chan.getGraph;
import static org.floens.chan.utils.AndroidUtils.dp;
import static org.floens.chan.utils.AndroidUtils.getAttrColor;
-public class SiteSetupController extends StyledToolbarNavigationController implements View.OnClickListener, SetupPresenter.Callback {
+public class SiteSetupController extends StyledToolbarNavigationController implements View.OnClickListener, SiteSetupPresenter.Callback {
+ @Inject
+ SiteSetupPresenter presenter;
+
private EditText url;
private View urlSubmit;
private View spinner;
@@ -64,8 +70,6 @@ public class SiteSetupController extends StyledToolbarNavigationController imple
private boolean blocked = false;
- private SetupPresenter presenter;
-
private RecyclerView sitesRecyclerview;
private SitesAdapter sitesAdapter;
private List sites = new ArrayList<>();
@@ -78,6 +82,8 @@ public class SiteSetupController extends StyledToolbarNavigationController imple
public void onCreate() {
super.onCreate();
+ getGraph().inject(this);
+
view = inflateRes(R.layout.controller_site_setup);
navigationItem.setTitle(R.string.setup_title);
@@ -90,8 +96,6 @@ public class SiteSetupController extends StyledToolbarNavigationController imple
next = (Button) view.findViewById(R.id.next_button);
next.setOnClickListener(this);
- presenter = new SetupPresenter();
-
sitesAdapter = new SitesAdapter();
sitesRecyclerview.setAdapter(sitesAdapter);
@@ -106,6 +110,7 @@ public class SiteSetupController extends StyledToolbarNavigationController imple
presenter.onUrlSubmitClicked(url.getText().toString());
} else if (v == next) {
presenter.onNextClicked();
+// navigationController.popController(false);
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/drawable/ThumbDrawable.java b/Clover/app/src/main/java/org/floens/chan/ui/drawable/ThumbDrawable.java
deleted file mode 100644
index f03251b8..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/drawable/ThumbDrawable.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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 .
- */
-package org.floens.chan.ui.drawable;
-
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-
-import static org.floens.chan.utils.AndroidUtils.dp;
-
-public class ThumbDrawable extends Drawable {
- private Paint paint = new Paint();
- private Path path = new Path();
- private int width;
- private int height;
-
- public ThumbDrawable() {
- width = dp(40);
- height = dp(40);
-
- paint.setStrokeWidth(dp(2));
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeCap(Paint.Cap.BUTT);
- paint.setColor(0xff757575);
-
- path.reset();
- for (int i = 0; i < 3; i++) {
- int top = (int) (getMinimumHeight() / 2f + (i - 1) * dp(6));
- path.moveTo(dp(8), top);
- path.lineTo(getMinimumWidth() - dp(8), top);
- }
- path.close();
- }
-
- @Override
- public void draw(Canvas canvas) {
- canvas.drawPath(path, paint);
- }
-
- @Override
- public int getIntrinsicWidth() {
- return width;
- }
-
- @Override
- public int getIntrinsicHeight() {
- return height;
- }
-
- @Override
- public void setAlpha(int alpha) {
- paint.setAlpha(alpha);
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- paint.setColorFilter(cf);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/helper/PostHelper.java b/Clover/app/src/main/java/org/floens/chan/ui/helper/PostHelper.java
index 28938ef6..376da0d5 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/helper/PostHelper.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/helper/PostHelper.java
@@ -25,8 +25,9 @@ import android.text.TextUtils;
import android.text.style.ImageSpan;
import org.floens.chan.R;
-import org.floens.chan.core.model.orm.Loadable;
import org.floens.chan.core.model.Post;
+import org.floens.chan.core.model.orm.Board;
+import org.floens.chan.core.model.orm.Loadable;
import org.floens.chan.utils.AndroidUtils;
import java.text.SimpleDateFormat;
@@ -86,6 +87,14 @@ public class PostHelper {
}
}
+ public static String formatSiteAndBoardName(Board board) {
+ return board.site.name() + " \u2013 /" + board.name + "/";
+ }
+
+ public static String formatBoardCodeAndName(Board board) {
+ return "/" + board.code + "/ \u2013 " + board.name;
+ }
+
private static SimpleDateFormat dateFormat = new SimpleDateFormat("LL/dd/yy(EEE)HH:mm:ss", Locale.US);
private static Date tmpDate = new Date();
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 3fa352ba..e7a3b706 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
@@ -241,7 +241,7 @@ public class FilterLayout extends LinearLayout implements View.OnClickListener {
final Spinner spinner = (Spinner) selectLayout.findViewById(R.id.progress);
- final List extends Site> allSites = Sites.ALL_SITES;
+ final List extends Site> allSites = Sites.allSites();
final Site[] selectedSite = {allSites.get(0)};
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadSlidingPaneLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadSlidingPaneLayout.java
index 05cd774f..00ab2c09 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadSlidingPaneLayout.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadSlidingPaneLayout.java
@@ -21,10 +21,12 @@ import android.content.Context;
import android.os.Parcelable;
import android.support.v4.widget.SlidingPaneLayout;
import android.util.AttributeSet;
+import android.view.View;
import android.view.ViewGroup;
import org.floens.chan.R;
import org.floens.chan.ui.controller.ThreadSlideController;
+import org.floens.chan.utils.AndroidUtils;
import static org.floens.chan.utils.AndroidUtils.dp;
@@ -53,6 +55,21 @@ public class ThreadSlidingPaneLayout extends SlidingPaneLayout {
rightPane = (ViewGroup) findViewById(R.id.right_pane);
}
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ // Forces a relayout after it has already been layed out, because SlidingPaneLayout sucks and otherwise
+ // gives the children too much room until they request a relayout.
+ AndroidUtils.waitForLayout(this, new AndroidUtils.OnMeasuredCallback() {
+ @Override
+ public boolean onMeasured(View view) {
+ requestLayout();
+ return false;
+ }
+ });
+ }
+
public void setThreadSlideController(ThreadSlideController threadSlideController) {
this.threadSlideController = threadSlideController;
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/LoadView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/LoadView.java
index ab2a0f9f..2a042c50 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/LoadView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/LoadView.java
@@ -100,7 +100,6 @@ public class LoadView extends FrameLayout {
public View setView(View newView, boolean animate) {
if (newView == null) {
FrameLayout progressBar = new FrameLayout(getContext());
- progressBar.setVisibility(View.GONE);
progressBar.addView(new ProgressBar(getContext()), new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER));
newView = progressBar;
}
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_reorder_black_24dp.png b/Clover/app/src/main/res/drawable-hdpi/ic_reorder_black_24dp.png
new file mode 100644
index 00000000..142d7150
Binary files /dev/null and b/Clover/app/src/main/res/drawable-hdpi/ic_reorder_black_24dp.png differ
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_reorder_black_24dp.png b/Clover/app/src/main/res/drawable-mdpi/ic_reorder_black_24dp.png
new file mode 100644
index 00000000..d18997cd
Binary files /dev/null and b/Clover/app/src/main/res/drawable-mdpi/ic_reorder_black_24dp.png differ
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_reorder_black_24dp.png b/Clover/app/src/main/res/drawable-xhdpi/ic_reorder_black_24dp.png
new file mode 100644
index 00000000..0b080a18
Binary files /dev/null and b/Clover/app/src/main/res/drawable-xhdpi/ic_reorder_black_24dp.png differ
diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_reorder_black_24dp.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_reorder_black_24dp.png
new file mode 100644
index 00000000..0a66529b
Binary files /dev/null and b/Clover/app/src/main/res/drawable-xxhdpi/ic_reorder_black_24dp.png differ
diff --git a/Clover/app/src/main/res/drawable-xxxhdpi/ic_reorder_black_24dp.png b/Clover/app/src/main/res/drawable-xxxhdpi/ic_reorder_black_24dp.png
new file mode 100644
index 00000000..56a5bc8b
Binary files /dev/null and b/Clover/app/src/main/res/drawable-xxxhdpi/ic_reorder_black_24dp.png differ
diff --git a/Clover/app/src/main/res/layout/cell_board_edit.xml b/Clover/app/src/main/res/layout/cell_board_edit.xml
index 52a498c5..09ab76f4 100644
--- a/Clover/app/src/main/res/layout/cell_board_edit.xml
+++ b/Clover/app/src/main/res/layout/cell_board_edit.xml
@@ -15,7 +15,8 @@ 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 .
-->
-.
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:scaleType="center"
- tools:ignore="ContentDescription" />
+ android:src="@drawable/ic_reorder_black_24dp"
+ tools:ignore="ContentDescription"/>
.
android:paddingTop="8dp"
android:singleLine="true"
android:textColor="?text_color_primary"
- android:textSize="14sp" />
+ android:textSize="14sp"/>
.
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="?text_color_secondary"
- android:textSize="12sp" />
+ android:textSize="12sp"/>
diff --git a/Clover/app/src/main/res/layout/cell_board_suggestion.xml b/Clover/app/src/main/res/layout/cell_board_suggestion.xml
new file mode 100644
index 00000000..82aa841a
--- /dev/null
+++ b/Clover/app/src/main/res/layout/cell_board_suggestion.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/Clover/app/src/main/res/layout/cell_saved_board.xml b/Clover/app/src/main/res/layout/cell_saved_board.xml
index 82aa841a..c32e3a41 100644
--- a/Clover/app/src/main/res/layout/cell_saved_board.xml
+++ b/Clover/app/src/main/res/layout/cell_saved_board.xml
@@ -39,4 +39,11 @@ along with this program. If not, see .
android:textColor="?text_color_primary"
android:textSize="14sp"/>
+
+
diff --git a/Clover/app/src/main/res/layout/controller_board_setup.xml b/Clover/app/src/main/res/layout/controller_board_setup.xml
index 774e2783..cb5deac5 100644
--- a/Clover/app/src/main/res/layout/controller_board_setup.xml
+++ b/Clover/app/src/main/res/layout/controller_board_setup.xml
@@ -20,7 +20,8 @@ along with this program. If not, see .
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="?attr/backcolor">
+ android:background="?attr/backcolor"
+ android:clipChildren="false">
.
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="0dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
diff --git a/docs/database.txt b/docs/database.txt
index c59f9576..02ad0630 100644
--- a/docs/database.txt
+++ b/docs/database.txt
@@ -67,6 +67,7 @@ ALTER TABLE loadable ADD COLUMN lastLoaded default -1;
Changes in version 22:
+CREATE TABLE `site` (`configuration` VARCHAR , `id` INTEGER PRIMARY KEY AUTOINCREMENT , `userSettings` VARCHAR );
ALTER TABLE loadable ADD COLUMN site INTEGER default 0;
ALTER TABLE board ADD COLUMN site INTEGER default 0;
ALTER TABLE savedreply ADD COLUMN site INTEGER default 0;