diff --git a/Clover/app/src/main/java/org/floens/chan/chan/ChanLoader.java b/Clover/app/src/main/java/org/floens/chan/chan/ChanLoader.java index 13e98882..fa2d520a 100644 --- a/Clover/app/src/main/java/org/floens/chan/chan/ChanLoader.java +++ b/Clover/app/src/main/java/org/floens/chan/chan/ChanLoader.java @@ -265,7 +265,7 @@ public class ChanLoader implements Response.ErrorListener, Response.Listener * All {@code final} fields are thread-safe. @@ -45,6 +49,11 @@ public class Post { public final String subject; + /** + * Unix timestamp, in seconds. + */ + public final long time; + public final PostImage image; public final String tripcode; @@ -57,12 +66,7 @@ public class Post { public final String countryName; - /** - * Unix timestamp, in seconds. - */ - public final long time; - - public final String countryUrl; + public final HttpUrl countryUrl; public final boolean isSavedReply; @@ -83,24 +87,28 @@ public class Post { public final CharSequence nameTripcodeIdCapcodeSpan; - // These members may only mutate on the main thread. - public boolean sticky = false; - public boolean closed = false; - public boolean archived = false; - public int replies = -1; - public int images = -1; - public int uniqueIps = 1; - public String title = ""; - - // Atomic, any thread. + /** + * This post has been deleted (the server isn't sending it anymore). + *

This boolean is modified in worker threads, use {@code .get()} to access it. + */ public final AtomicBoolean deleted = new AtomicBoolean(false); /** - * These ids replied to this post.
- * synchronize on this when accessing. + * These ids replied to this post. + *

Manual synchronization is needed, since this list can be modified from any thread. + * Wrap all accesses in a {@code synchronized} block. */ public final List repliesFrom = new ArrayList<>(); + // These members may only mutate on the main thread. + private boolean sticky = false; + private boolean closed = false; + private boolean archived = false; + private int replies = -1; + private int images = -1; + private int uniqueIps = 1; + private String title = ""; + private Post(Builder builder) { board = builder.board; boardId = builder.board.code; @@ -142,6 +150,76 @@ public class Post { repliesTo = Collections.unmodifiableSet(builder.repliesToIds); } + @MainThread + public boolean isSticky() { + return sticky; + } + + @MainThread + public void setSticky(boolean sticky) { + this.sticky = sticky; + } + + @MainThread + public boolean isClosed() { + return closed; + } + + @MainThread + public void setClosed(boolean closed) { + this.closed = closed; + } + + @MainThread + public boolean isArchived() { + return archived; + } + + @MainThread + public void setArchived(boolean archived) { + this.archived = archived; + } + + @MainThread + public int getReplies() { + return replies; + } + + @MainThread + public void setReplies(int replies) { + this.replies = replies; + } + + @MainThread + public int getImages() { + return images; + } + + @MainThread + public void setImages(int images) { + this.images = images; + } + + @MainThread + public int getUniqueIps() { + return uniqueIps; + } + + @MainThread + public void setUniqueIps(int uniqueIps) { + this.uniqueIps = uniqueIps; + } + + @MainThread + public String getTitle() { + return title; + } + + @MainThread + public void setTitle(String title) { + this.title = title; + } + public static final class Builder { public Board board; public int id = -1; @@ -165,7 +243,7 @@ public class Post { public String countryCode; public String countryName; - public String countryUrl; + public HttpUrl countryUrl; public String posterId = ""; public String moderatorCapcode = ""; @@ -275,7 +353,7 @@ public class Post { return this; } - public Builder country(String countryCode, String countryName, String countryUrl) { + public Builder country(String countryCode, String countryName, HttpUrl countryUrl) { this.countryCode = countryCode; this.countryName = countryName; this.countryUrl = countryUrl; diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java b/Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java index c4ed6524..74d1a0c4 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java +++ b/Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java @@ -19,14 +19,16 @@ package org.floens.chan.core.model; import org.floens.chan.core.settings.ChanSettings; +import okhttp3.HttpUrl; + public class PostImage { public enum Type { STATIC, GIF, MOVIE } public final String originalName; - public final String thumbnailUrl; - public final String imageUrl; + public final HttpUrl thumbnailUrl; + public final HttpUrl imageUrl; public final String filename; public final String extension; public final int imageWidth; @@ -62,8 +64,8 @@ public class PostImage { public static final class Builder { private String originalName; - private String thumbnailUrl; - private String imageUrl; + private HttpUrl thumbnailUrl; + private HttpUrl imageUrl; private String filename; private String extension; private int imageWidth; @@ -79,12 +81,12 @@ public class PostImage { return this; } - public Builder thumbnailUrl(String thumbnailUrl) { + public Builder thumbnailUrl(HttpUrl thumbnailUrl) { this.thumbnailUrl = thumbnailUrl; return this; } - public Builder imageUrl(String imageUrl) { + public Builder imageUrl(HttpUrl imageUrl) { this.imageUrl = imageUrl; return this; } diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java index ae08de2a..1263f4f5 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java @@ -271,7 +271,7 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager. private boolean imageAutoLoad(PostImage postImage) { // Auto load the image when it is cached - return fileCache.exists(postImage.imageUrl) || shouldLoadForNetworkType(ChanSettings.imageAutoLoadNetwork.get()); + return fileCache.exists(postImage.imageUrl.toString()) || shouldLoadForNetworkType(ChanSettings.imageAutoLoadNetwork.get()); } private boolean videoAutoLoad(PostImage postImage) { diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java index 7d5b70eb..570b8bec 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java @@ -197,18 +197,10 @@ public class ReplyPresenter implements CaptchaCallback, ImagePickDelegate.ImageP callback.loadViewsIntoDraft(draft); draft.loadable = loadable; - if (ChanSettings.passLoggedIn()) { - draft.noVerification = true; - draft.passId = ChanSettings.passId.get(); - } else { - draft.noVerification = false; - draft.passId = null; - } - draft.spoilerImage = draft.spoilerImage && board.spoilers; draft.captchaResponse = null; - if (draft.noVerification) { + if (loadable.getSite().isLoggedIn()) { makeSubmitCall(); } else { switchPage(Page.CAPTCHA, true); diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java index 053b0bd8..153593f4 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java @@ -612,7 +612,8 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt databaseManager.getDatabaseSavedReplyManager().findSavedReply(post.boardId, post.no) ); if (reply != null) { - loadable.getSite().delete(new DeleteRequest(loadable.getSite(), post, reply, onlyImageDelete), new Site.DeleteListener() { + Site site = loadable.getSite(); + site.delete(new DeleteRequest(post, reply, onlyImageDelete), new Site.DeleteListener() { @Override public void onDeleteComplete(HttpCall httpPost, DeleteResponse deleteResponse) { String message; @@ -698,7 +699,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt History history = new History(); history.loadable = loadable; PostImage image = chanLoader.getThread().op.image; - history.thumbnailUrl = image == null ? "" : image.thumbnailUrl; + history.thumbnailUrl = image == null ? "" : image.thumbnailUrl.toString(); databaseManager.getDatabaseHistoryManager().add(history); } } diff --git a/Clover/app/src/main/java/org/floens/chan/core/saver/ImageSaveTask.java b/Clover/app/src/main/java/org/floens/chan/core/saver/ImageSaveTask.java index f2b297aa..321f99fc 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/saver/ImageSaveTask.java +++ b/Clover/app/src/main/java/org/floens/chan/core/saver/ImageSaveTask.java @@ -118,7 +118,7 @@ public class ImageSaveTask implements Runnable, FileCache.DownloadedCallback { if (destination.exists()) { onDestination(); } else { - FileCache.FileCacheDownloader fileCacheDownloader = fileCache.downloadFile(postImage.imageUrl, this); + FileCache.FileCacheDownloader fileCacheDownloader = fileCache.downloadFile(postImage.imageUrl.toString(), this); // If the fileCacheDownloader is null then the destination already existed and onSuccess() has been called. // Wait otherwise for the download to finish to avoid that the next task is immediately executed. if (fileCacheDownloader != null) { diff --git a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java index f7d42941..a4694bbf 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java +++ b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java @@ -141,10 +141,6 @@ public class ChanSettings { public static final BooleanSetting watchPeek; public static final StringSetting watchLed; - public static final StringSetting passToken; - public static final StringSetting passPin; - public static final StringSetting passId; - public static final BooleanSetting historyEnabled; public static final IntegerSetting previousVersion; @@ -158,22 +154,6 @@ public class ChanSettings { public static final CounterSetting replyOpenCounter; public static final CounterSetting threadOpenCounter; - public enum TestOptions implements OptionSettingItem { - ONE("one"), - TWO("two"), - THREE("three"); - - String name; - - TestOptions(String name) { - this.name = name; - } - - public String getName() { - return name; - } - } - static { SharedPreferences p = AndroidUtils.getPreferences(); @@ -251,10 +231,6 @@ public class ChanSettings { watchPeek = new BooleanSetting(p, "preference_watch_peek", true); watchLed = new StringSetting(p, "preference_watch_led", "ffffffff"); - passToken = new StringSetting(p, "preference_pass_token", ""); - passPin = new StringSetting(p, "preference_pass_pin", ""); - passId = new StringSetting(p, "preference_pass_id", ""); - historyEnabled = new BooleanSetting(p, "preference_history_enabled", true); previousVersion = new IntegerSetting(p, "preference_previous_version", 0); @@ -295,10 +271,6 @@ public class ChanSettings { // preference_watch_background_timeout "60" the old timeout background setting in minutes } - public static boolean passLoggedIn() { - return passId.get().length() > 0; - } - public static ThemeColor getThemeAndColor() { String themeRaw = ChanSettings.theme.get(); 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 ee124932..69269fc3 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 @@ -17,6 +17,8 @@ */ package org.floens.chan.core.site; +import android.support.annotation.Nullable; + import org.floens.chan.chan.ChanLoaderRequest; import org.floens.chan.chan.ChanLoaderRequestParams; import org.floens.chan.core.model.Board; @@ -56,7 +58,7 @@ public interface Site { POST_REPORT, /** - * This site supports some sort of login (like 4pass). + * This site supports some sort of authentication (like 4pass). * * @see #login(LoginRequest, LoginListener) * @see SiteEndpoints#login() @@ -113,8 +115,12 @@ public interface Site { SiteEndpoints endpoints(); + SiteRequestModifier requestModifier(); + BoardsType boardsType(); + String desktopUrl(Loadable loadable, @Nullable Post post); + void boards(BoardsListener boardsListener); interface BoardsListener { @@ -141,8 +147,18 @@ public interface Site { void onDeleteError(HttpCall httpCall); } + /* TODO(multi-site) this login mechanism is probably not generic enough right now, + * especially if we're thinking about what a login really is + * We'll expand this later when we have a better idea of what other sites require. + */ void login(LoginRequest loginRequest, LoginListener loginListener); + void logout(); + + boolean isLoggedIn(); + + LoginRequest getLoginDetails(); + interface LoginListener { void onLoginComplete(HttpCall httpCall, LoginResponse loginResponse); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteEndpoints.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteEndpoints.java index e184fe5f..756d2958 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/SiteEndpoints.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteEndpoints.java @@ -23,27 +23,29 @@ import org.floens.chan.core.model.Post; import java.util.Map; +import okhttp3.HttpUrl; + /** * Endpoints for {@link Site}. */ public interface SiteEndpoints { - String catalog(Board board); + HttpUrl catalog(Board board); - String thread(Board board, Loadable loadable); + HttpUrl thread(Board board, Loadable loadable); - String imageUrl(Post.Builder post, Map arg); + HttpUrl imageUrl(Post.Builder post, Map arg); - String thumbnailUrl(Post.Builder post, boolean spoiler, Map arg); + HttpUrl thumbnailUrl(Post.Builder post, boolean spoiler, Map arg); - String flag(Post.Builder post, String countryCode, Map arg); + HttpUrl flag(Post.Builder post, String countryCode, Map arg); - String boards(); + HttpUrl boards(); - String reply(Loadable thread); + HttpUrl reply(Loadable thread); - String delete(Post post); + HttpUrl delete(Post post); - String report(Post post); + HttpUrl report(Post post); - String login(); + HttpUrl login(); } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteRequestModifier.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteRequestModifier.java new file mode 100644 index 00000000..e7351c89 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteRequestModifier.java @@ -0,0 +1,31 @@ +/* + * 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; + + +import android.webkit.WebView; + +import org.floens.chan.core.site.http.HttpCall; + +import okhttp3.Request; + +public interface SiteRequestModifier { + void modifyHttpCall(HttpCall httpCall, Request.Builder requestBuilder); + + void modifyWebView(WebView webView); +} 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 225e63fb..d3ee243d 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 @@ -1,6 +1,9 @@ package org.floens.chan.core.site; +import android.content.SharedPreferences; + import org.floens.chan.core.site.sites.chan4.Chan4; +import org.floens.chan.utils.AndroidUtils; import java.util.Arrays; import java.util.List; @@ -34,4 +37,8 @@ public class Sites { public static Site defaultSite() { return CHAN4; } + + public static SharedPreferences getPreferences(Site site) { + return AndroidUtils.getPreferences(site.id() + "_site_preferences"); + } } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/http/DeleteRequest.java b/Clover/app/src/main/java/org/floens/chan/core/site/http/DeleteRequest.java index 44187cce..6bb68843 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/http/DeleteRequest.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/http/DeleteRequest.java @@ -20,16 +20,13 @@ package org.floens.chan.core.site.http; import org.floens.chan.core.model.Post; import org.floens.chan.core.model.SavedReply; -import org.floens.chan.core.site.Site; public class DeleteRequest { - public final Site site; public final Post post; public final SavedReply savedReply; public final boolean imageOnly; - public DeleteRequest(Site site, Post post, SavedReply savedReply, boolean imageOnly) { - this.site = site; + public DeleteRequest(Post post, SavedReply savedReply, boolean imageOnly) { this.post = post; this.savedReply = savedReply; this.imageOnly = imageOnly; diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCall.java index 94b47a90..310eff26 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCall.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCall.java @@ -17,6 +17,7 @@ */ package org.floens.chan.core.site.http; +import org.floens.chan.core.site.Site; import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.IOUtils; import org.floens.chan.utils.Logger; @@ -38,6 +39,8 @@ import okhttp3.Response; public abstract class HttpCall implements Callback { private static final String TAG = "HttpCall"; + protected Site site; + private boolean successful = false; private HttpCallback callback; private Exception exception; @@ -46,6 +49,10 @@ public abstract class HttpCall implements Callback { public abstract void process(Response response, String result) throws IOException; + public HttpCall(Site site) { + this.site = site; + } + @Override public void onResponse(Call call, Response response) { try { diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCallManager.java b/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCallManager.java index 998654a0..2fb8a005 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCallManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCallManager.java @@ -19,6 +19,7 @@ package org.floens.chan.core.site.http; import org.floens.chan.core.di.UserAgentProvider; +import org.floens.chan.core.site.Site; import java.util.concurrent.TimeUnit; @@ -53,8 +54,13 @@ public class HttpCallManager { Request.Builder requestBuilder = new Request.Builder(); + Site site = httpCall.site; httpCall.setup(requestBuilder); + if (site != null) { + site.requestModifier().modifyHttpCall(httpCall, requestBuilder); + } + requestBuilder.header("User-Agent", userAgentProvider.getUserAgent()); Request request = requestBuilder.build(); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/http/LoginRequest.java b/Clover/app/src/main/java/org/floens/chan/core/site/http/LoginRequest.java index d35d3653..0d47c907 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/http/LoginRequest.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/http/LoginRequest.java @@ -18,15 +18,11 @@ package org.floens.chan.core.site.http; -import org.floens.chan.core.site.Site; - public class LoginRequest { - public final Site site; public final String user; public final String pass; - public LoginRequest(Site site, String user, String pass) { - this.site = site; + public LoginRequest(String user, String pass) { this.user = user; this.pass = pass; } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/http/Reply.java b/Clover/app/src/main/java/org/floens/chan/core/site/http/Reply.java index a87c37cb..3acf40c2 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/http/Reply.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/http/Reply.java @@ -35,12 +35,8 @@ public class Reply { */ public String captchaResponse; - // TODO(multi-site) flip boolean - public boolean noVerification = false; - public Loadable loadable; - public String passId; public File file; public String fileName = ""; public String name = ""; 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 f4348f4e..2b68ac42 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 @@ -17,6 +17,11 @@ */ package org.floens.chan.core.site.sites.chan4; +import android.content.SharedPreferences; +import android.support.annotation.Nullable; +import android.webkit.CookieManager; +import android.webkit.WebView; + import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; @@ -26,14 +31,18 @@ import org.floens.chan.chan.ChanLoaderRequestParams; import org.floens.chan.core.model.Board; import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Post; +import org.floens.chan.core.settings.StringSetting; import org.floens.chan.core.site.Boards; import org.floens.chan.core.site.Site; import org.floens.chan.core.site.SiteEndpoints; +import org.floens.chan.core.site.SiteRequestModifier; import org.floens.chan.core.site.http.DeleteRequest; import org.floens.chan.core.site.http.HttpCall; import org.floens.chan.core.site.http.HttpCallManager; import org.floens.chan.core.site.http.LoginRequest; +import org.floens.chan.core.site.http.LoginResponse; import org.floens.chan.core.site.http.Reply; +import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.Logger; import java.util.ArrayList; @@ -45,6 +54,9 @@ import java.util.Random; import javax.inject.Inject; +import okhttp3.HttpUrl; +import okhttp3.Request; + import static org.floens.chan.Chan.getGraph; public class Chan4 implements Site { @@ -59,68 +71,171 @@ public class Chan4 implements Site { RequestQueue requestQueue; private final SiteEndpoints endpoints = new SiteEndpoints() { + private final HttpUrl a = new HttpUrl.Builder() + .scheme("https") + .host("a.4cdn.org") + .build(); + + private final HttpUrl i = new HttpUrl.Builder() + .scheme("https") + .host("i.4cdn.org") + .build(); + + private final HttpUrl t = new HttpUrl.Builder() + .scheme("https") + .host("t.4cdn.org") + .build(); + + private final HttpUrl s = new HttpUrl.Builder() + .scheme("https") + .host("s.4cdn.org") + .build(); + + private final HttpUrl sys = new HttpUrl.Builder() + .scheme("https") + .host("sys.4chan.org") + .build(); + @Override - public String catalog(Board board) { - return "https://a.4cdn.org/" + board.code + "/catalog.json"; + public HttpUrl catalog(Board board) { + return a.newBuilder() + .addPathSegment(board.code) + .addPathSegment("catalog.json") + .build(); } @Override - public String thread(Board board, Loadable loadable) { - return "https://a.4cdn.org/" + board.code + "/thread/" + loadable.no + ".json"; + public HttpUrl thread(Board board, Loadable loadable) { + return a.newBuilder() + .addPathSegment(board.code) + .addPathSegment("thread") + .addPathSegment(loadable.no + ".json") + .build(); } @Override - public String imageUrl(Post.Builder post, Map arg) { - return "https://i.4cdn.org/" + post.board.code + "/" + arg.get("tim") + "." + arg.get("ext"); + public HttpUrl imageUrl(Post.Builder post, Map arg) { + return i.newBuilder() + .addPathSegment(post.board.code) + .addPathSegment(arg.get("tim") + "." + arg.get("ext")) + .build(); } @Override - public String thumbnailUrl(Post.Builder post, boolean spoiler, Map arg) { + public HttpUrl thumbnailUrl(Post.Builder post, boolean spoiler, Map arg) { if (spoiler) { + HttpUrl.Builder image = s.newBuilder() + .addPathSegment("image"); if (post.board.customSpoilers >= 0) { int i = random.nextInt(post.board.customSpoilers) + 1; - return "https://s.4cdn.org/image/spoiler-" + post.board.code + i + ".png"; + image.addPathSegment("spoiler-" + post.board.code + i + ".png"); } else { - return "https://s.4cdn.org/image/spoiler.png"; + image.addPathSegment("spoiler.png"); } + return image.build(); } else { - return "https://t.4cdn.org/" + post.board.code + "/" + arg.get("tim") + "s.jpg"; + return t.newBuilder() + .addPathSegment(post.board.code) + .addPathSegment(arg.get("tim") + "s.jpg") + .build(); } } @Override - public String flag(Post.Builder post, String countryCode, Map arg) { - return "https://s.4cdn.org/image/country/" + countryCode.toLowerCase(Locale.ENGLISH) + ".gif"; + public HttpUrl flag(Post.Builder post, String countryCode, Map arg) { + return s.newBuilder() + .addPathSegment("image") + .addPathSegment("country") + .addPathSegment(countryCode.toLowerCase(Locale.ENGLISH) + ".gif") + .build(); } @Override - public String boards() { - return "https://a.4cdn.org/boards.json"; + public HttpUrl boards() { + return a.newBuilder() + .addPathSegment("boards.json") + .build(); } @Override - public String reply(Loadable loadable) { - return "https://sys.4chan.org/" + loadable.getBoard().code + "/post"; + public HttpUrl reply(Loadable loadable) { + return sys.newBuilder() + .addPathSegment(loadable.board.code) + .addPathSegment("post") + .build(); } @Override - public String delete(Post post) { - return "https://sys.4chan.org/" + post.board.code + "/imgboard.php"; + public HttpUrl delete(Post post) { + return sys.newBuilder() + .addPathSegment(post.board.code) + .addPathSegment("imgboard.php") + .build(); } @Override - public String report(Post post) { - return "https://sys.4chan.org/" + post.board.code + "/imgboard.php?mode=report&no=" + post.no; + public HttpUrl report(Post post) { + return sys.newBuilder() + .addPathSegment(post.board.code) + .addPathSegment("imgboard.php") + .addQueryParameter("mode", "report") + .addQueryParameter("no", String.valueOf(post.no)) + .build(); } @Override - public String login() { - return "https://sys.4chan.org/auth"; + public HttpUrl login() { + return sys.newBuilder() + .addPathSegment("auth") + .build(); } }; + private SiteRequestModifier siteRequestModifier = new SiteRequestModifier() { + @Override + public void modifyHttpCall(HttpCall httpCall, Request.Builder requestBuilder) { + if (isLoggedIn()) { + requestBuilder.addHeader("Cookie", "pass_id=" + passToken.get()); + } + } + + @SuppressWarnings("deprecation") + @Override + public void modifyWebView(WebView webView) { + final HttpUrl sys = new HttpUrl.Builder() + .scheme("https") + .host("sys.4chan.org") + .build(); + + CookieManager cookieManager = CookieManager.getInstance(); + cookieManager.removeAllCookie(); + if (isLoggedIn()) { + String[] passCookies = { + "pass_enabled=1;", + "pass_id=" + passToken.get() + ";" + }; + String domain = sys.scheme() + "://" + sys.host() + "/"; + for (String cookie : passCookies) { + cookieManager.setCookie(domain, cookie); + } + } + } + }; + + // Legacy settings that were global before + private final StringSetting passUser; + private final StringSetting passPass; + private final StringSetting passToken; + public Chan4() { getGraph().inject(this); + + SharedPreferences p = AndroidUtils.getPreferences(); + passUser = new StringSetting(p, "preference_pass_token", ""); + passPass = new StringSetting(p, "preference_pass_pin", ""); + // token was renamed, before it meant the username, now it means the token returned + // from the server that the cookie is set to. + passToken = new StringSetting(p, "preference_pass_id", ""); } /** @@ -160,6 +275,21 @@ public class Chan4 implements Site { return BoardsType.DYNAMIC; } + @Override + public String desktopUrl(Loadable loadable, @Nullable Post post) { + if (loadable.isCatalogMode()) { + return "https://boards.4chan.org/" + loadable.board.code + "/"; + } else if (loadable.isThreadMode()) { + String url = "https://boards.4chan.org/" + loadable.board.code + "/thread/" + loadable.no; + if (post != null) { + url += "#p" + post.no; + } + return url; + } else { + throw new IllegalArgumentException(); + } + } + @Override public boolean boardFeature(BoardFeature boardFeature, Board board) { switch (boardFeature) { @@ -191,6 +321,11 @@ public class Chan4 implements Site { return endpoints; } + @Override + public SiteRequestModifier requestModifier() { + return siteRequestModifier; + } + @Override public void boards(final BoardsListener listener) { requestQueue.add(new Chan4BoardsRequest(this, new Response.Listener>() { @@ -222,7 +357,7 @@ public class Chan4 implements Site { @Override public void post(Reply reply, final PostListener postListener) { - httpCallManager.makeHttpCall(new Chan4ReplyHttpCall(reply), new HttpCall.HttpCallback() { + httpCallManager.makeHttpCall(new Chan4ReplyHttpCall(this, reply), new HttpCall.HttpCallback() { @Override public void onHttpSuccess(Chan4ReplyHttpCall httpPost) { postListener.onPostComplete(httpPost, httpPost.replyResponse); @@ -237,7 +372,7 @@ public class Chan4 implements Site { @Override public void delete(DeleteRequest deleteRequest, final DeleteListener deleteListener) { - httpCallManager.makeHttpCall(new Chan4DeleteHttpCall(deleteRequest), new HttpCall.HttpCallback() { + httpCallManager.makeHttpCall(new Chan4DeleteHttpCall(this, deleteRequest), new HttpCall.HttpCallback() { @Override public void onHttpSuccess(Chan4DeleteHttpCall httpPost) { deleteListener.onDeleteComplete(httpPost, httpPost.deleteResponse); @@ -252,10 +387,17 @@ public class Chan4 implements Site { @Override public void login(LoginRequest loginRequest, final LoginListener loginListener) { - httpCallManager.makeHttpCall(new Chan4PassHttpCall(loginRequest), new HttpCall.HttpCallback() { + passUser.set(loginRequest.user); + passPass.set(loginRequest.pass); + + httpCallManager.makeHttpCall(new Chan4PassHttpCall(this, loginRequest), new HttpCall.HttpCallback() { @Override public void onHttpSuccess(Chan4PassHttpCall httpCall) { - loginListener.onLoginComplete(httpCall, httpCall.loginResponse); + LoginResponse loginResponse = httpCall.loginResponse; + if (loginResponse.success) { + passToken.set(loginResponse.token); + } + loginListener.onLoginComplete(httpCall, loginResponse); } @Override @@ -264,4 +406,19 @@ public class Chan4 implements Site { } }); } + + @Override + public void logout() { + passToken.set(""); + } + + @Override + public boolean isLoggedIn() { + return !passToken.get().isEmpty(); + } + + @Override + public LoginRequest getLoginDetails() { + return new LoginRequest(passUser.get(), passPass.get()); + } } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4BoardsRequest.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4BoardsRequest.java index 6ef43c6d..c5886843 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4BoardsRequest.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4BoardsRequest.java @@ -43,7 +43,7 @@ public class Chan4BoardsRequest extends JsonReaderRequest> { private final Site site; public Chan4BoardsRequest(Site site, Listener> listener, ErrorListener errorListener) { - super(site.endpoints().boards(), listener, errorListener); + super(site.endpoints().boards().toString(), listener, errorListener); this.site = site; } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4DeleteHttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4DeleteHttpCall.java index ae15969e..da3e4dc6 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4DeleteHttpCall.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4DeleteHttpCall.java @@ -17,6 +17,7 @@ */ package org.floens.chan.core.site.sites.chan4; +import org.floens.chan.core.site.Site; import org.floens.chan.core.site.http.DeleteRequest; import org.floens.chan.core.site.http.DeleteResponse; import org.floens.chan.core.site.http.HttpCall; @@ -36,7 +37,8 @@ public class Chan4DeleteHttpCall extends HttpCall { private final DeleteRequest deleteRequest; public final DeleteResponse deleteResponse = new DeleteResponse(); - public Chan4DeleteHttpCall(DeleteRequest deleteRequest) { + public Chan4DeleteHttpCall(Site site, DeleteRequest deleteRequest) { + super(site); this.deleteRequest = deleteRequest; } @@ -50,7 +52,7 @@ public class Chan4DeleteHttpCall extends HttpCall { formBuilder.add("mode", "usrdel"); formBuilder.add("pwd", deleteRequest.savedReply.password); - requestBuilder.url(deleteRequest.site.endpoints().delete(deleteRequest.post)); + requestBuilder.url(site.endpoints().delete(deleteRequest.post)); requestBuilder.post(formBuilder.build()); } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4PassHttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4PassHttpCall.java index a2cffa19..a82429f6 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4PassHttpCall.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4PassHttpCall.java @@ -17,6 +17,7 @@ */ package org.floens.chan.core.site.sites.chan4; +import org.floens.chan.core.site.Site; import org.floens.chan.core.site.http.HttpCall; import org.floens.chan.core.site.http.LoginRequest; import org.floens.chan.core.site.http.LoginResponse; @@ -33,7 +34,8 @@ public class Chan4PassHttpCall extends HttpCall { private final LoginRequest loginRequest; public final LoginResponse loginResponse = new LoginResponse(); - public Chan4PassHttpCall(LoginRequest loginRequest) { + public Chan4PassHttpCall(Site site, LoginRequest loginRequest) { + super(site); this.loginRequest = loginRequest; } @@ -46,7 +48,7 @@ public class Chan4PassHttpCall extends HttpCall { formBuilder.add("id", loginRequest.user); formBuilder.add("pin", loginRequest.pass); - requestBuilder.url(loginRequest.site.endpoints().login()); + requestBuilder.url(site.endpoints().login()); requestBuilder.post(formBuilder.build()); } 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/sites/chan4/Chan4ReaderRequest.java index c773dc2c..c203bbed 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/sites/chan4/Chan4ReaderRequest.java @@ -47,6 +47,8 @@ import java.util.concurrent.Future; import javax.inject.Inject; +import okhttp3.HttpUrl; + import static org.floens.chan.Chan.getGraph; /** @@ -84,7 +86,7 @@ public class Chan4ReaderRequest extends JsonReaderRequest { private long startLoad; public Chan4ReaderRequest(ChanLoaderRequestParams request) { - super(getChanUrl(request.loadable), request.listener, request.errorListener); + super(getChanUrl(request.loadable).toString(), request.listener, request.errorListener); getGraph().inject(this); // Copy the loadable and cached list. The cached array may changed/cleared by other threads. @@ -116,8 +118,8 @@ public class Chan4ReaderRequest extends JsonReaderRequest { databaseSavedReplyManager = databaseManager.getDatabaseSavedReplyManager(); } - private static String getChanUrl(Loadable loadable) { - String url; + private static HttpUrl getChanUrl(Loadable loadable) { + HttpUrl url; if (loadable.site == null) { throw new NullPointerException("Loadable.site == null"); @@ -497,7 +499,7 @@ public class Chan4ReaderRequest extends JsonReaderRequest { } if (countryCode != null && countryName != null) { - String countryUrl = endpoints.flag(builder, countryCode, Collections.emptyMap()); + HttpUrl countryUrl = endpoints.flag(builder, countryCode, Collections.emptyMap()); builder.country(countryCode, countryName, countryUrl); } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyHttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyHttpCall.java index c9c85540..b2595830 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyHttpCall.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyHttpCall.java @@ -46,7 +46,8 @@ public class Chan4ReplyHttpCall extends HttpCall { public final Reply reply; public final ReplyResponse replyResponse = new ReplyResponse(); - public Chan4ReplyHttpCall(Reply reply) { + public Chan4ReplyHttpCall(Site site, Reply reply) { + super(site); this.reply = reply; } @@ -75,7 +76,7 @@ public class Chan4ReplyHttpCall extends HttpCall { formBuilder.addFormDataPart("com", reply.comment); - if (!reply.noVerification) { + if (reply.captchaResponse != null) { if (reply.captchaChallenge != null) { formBuilder.addFormDataPart("recaptcha_challenge_field", reply.captchaChallenge); formBuilder.addFormDataPart("recaptcha_response_field", reply.captchaResponse); @@ -94,13 +95,8 @@ public class Chan4ReplyHttpCall extends HttpCall { formBuilder.addFormDataPart("spoiler", "on"); } - Site site = reply.loadable.getSite(); requestBuilder.url(site.endpoints().reply(reply.loadable)); requestBuilder.post(formBuilder.build()); - - if (reply.noVerification) { - requestBuilder.addHeader("Cookie", "pass_id=" + reply.passId); - } } @Override diff --git a/Clover/app/src/main/java/org/floens/chan/test/TestActivity.java b/Clover/app/src/main/java/org/floens/chan/test/TestActivity.java index a978b8e2..5a1e5374 100644 --- a/Clover/app/src/main/java/org/floens/chan/test/TestActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/test/TestActivity.java @@ -208,7 +208,7 @@ public class TestActivity extends Activity implements View.OnClickListener { public void onChanLoaderData(ChanThread result) { for (Post post : result.posts) { if (post.image != null) { - final String imageUrl = post.image.imageUrl; + final String imageUrl = post.image.imageUrl.toString(); fileCache.downloadFile(imageUrl, new FileCache.DownloadedCallback() { @Override public void onProgress(long downloaded, long total, boolean done) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostsFilter.java b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostsFilter.java index d0294755..0e69ee98 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostsFilter.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostsFilter.java @@ -37,14 +37,14 @@ public class PostsFilter { public static final Comparator IMAGE_COMPARATOR = new Comparator() { @Override public int compare(Post lhs, Post rhs) { - return rhs.images - lhs.images; + return rhs.getImages() - lhs.getImages(); } }; public static final Comparator REPLY_COMPARATOR = new Comparator() { @Override public int compare(Post lhs, Post rhs) { - return rhs.replies - lhs.replies; + return rhs.getReplies() - lhs.getReplies(); } }; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/cell/CardPostCell.java b/Clover/app/src/main/java/org/floens/chan/ui/cell/CardPostCell.java index a948e3d0..d6d7b5d7 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/cell/CardPostCell.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/cell/CardPostCell.java @@ -217,7 +217,7 @@ public class CardPostCell extends CardView implements PostCellInterface, View.On comment.setText(commentText); comment.setTextColor(theme.textPrimary); - replies.setText(getResources().getString(R.string.card_stats, post.replies, post.images)); + replies.setText(getResources().getString(R.string.card_stats, post.getReplies(), post.getImages())); } private void unbindPost(Post post) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/cell/PostCell.java b/Clover/app/src/main/java/org/floens/chan/ui/cell/PostCell.java index 3a5b8615..c9d16d2b 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/cell/PostCell.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/cell/PostCell.java @@ -51,7 +51,6 @@ import android.widget.TextView; import com.android.volley.VolleyError; import com.android.volley.toolbox.ImageLoader; -import org.floens.chan.Chan; import org.floens.chan.R; import org.floens.chan.core.model.Post; import org.floens.chan.core.model.PostImage; @@ -395,10 +394,10 @@ public class PostCell extends LinearLayout implements PostCellInterface { title.setText(TextUtils.concat(titleParts.toArray(new CharSequence[titleParts.size()]))); icons.edit(); - icons.set(PostIcons.STICKY, post.sticky); - icons.set(PostIcons.CLOSED, post.closed); + icons.set(PostIcons.STICKY, post.isSticky()); + icons.set(PostIcons.CLOSED, post.isClosed()); icons.set(PostIcons.DELETED, post.deleted.get()); - icons.set(PostIcons.ARCHIVED, post.archived); + icons.set(PostIcons.ARCHIVED, post.isArchived()); if (!isEmpty(post.country)) { icons.set(PostIcons.COUNTRY, true); @@ -445,14 +444,14 @@ public class PostCell extends LinearLayout implements PostCellInterface { repliesFromSize = post.repliesFrom.size(); } - if ((!threadMode && post.replies > 0) || (repliesFromSize > 0)) { + if ((!threadMode && post.getReplies() > 0) || (repliesFromSize > 0)) { replies.setVisibility(View.VISIBLE); - int replyCount = threadMode ? repliesFromSize : post.replies; + int replyCount = threadMode ? repliesFromSize : post.getReplies(); String text = getResources().getQuantityString(R.plurals.reply, replyCount, replyCount); - if (!threadMode && post.images > 0) { - text += ", " + getResources().getQuantityString(R.plurals.image, post.images, post.images); + if (!threadMode && post.getImages() > 0) { + text += ", " + getResources().getQuantityString(R.plurals.image, post.getImages(), post.getImages()); } replies.setText(text); @@ -674,7 +673,7 @@ public class PostCell extends LinearLayout implements PostCellInterface { countryTextColor = theme.detailsColor; countryTextSize = textSize; - countryIconRequest = getGraph().getImageLoader().get(post.countryUrl, new ImageLoader.ImageListener() { + countryIconRequest = getGraph().getImageLoader().get(post.countryUrl.toString(), new ImageLoader.ImageListener() { @Override public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) { if (response.getBitmap() != null) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java b/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java index 1d5398c2..abc0b046 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java @@ -29,7 +29,6 @@ import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; -import org.floens.chan.Chan; import org.floens.chan.R; import org.floens.chan.core.model.Board; import org.floens.chan.core.model.ChanThread; @@ -124,16 +123,16 @@ public class ThreadStatusCell extends LinearLayout implements View.OnClickListen Board board = op.board; if (board != null) { - SpannableString replies = new SpannableString(op.replies + "R"); - if (op.replies >= board.bumpLimit) { + SpannableString replies = new SpannableString(op.getReplies() + "R"); + if (op.getReplies() >= board.bumpLimit) { replies.setSpan(new StyleSpan(Typeface.ITALIC), 0, replies.length(), 0); } - SpannableString images = new SpannableString(op.images + "I"); - if (op.images >= board.imageLimit) { + SpannableString images = new SpannableString(op.getImages() + "I"); + if (op.getImages() >= board.imageLimit) { images.setSpan(new StyleSpan(Typeface.ITALIC), 0, images.length(), 0); } - text.setText(TextUtils.concat(statusText, replies, " / ", images, " / ", String.valueOf(op.uniqueIps) + "P")); + text.setText(TextUtils.concat(statusText, replies, " / ", images, " / ", String.valueOf(op.getUniqueIps()) + "P")); } return update; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java index 336a8dae..97490fa8 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java @@ -198,7 +198,7 @@ public class ImageViewerController extends Controller implements ImageViewerPres saveShare(true, postImage); break; case OPEN_BROWSER_ID: - AndroidUtils.openLinkInBrowser((Activity) context, postImage.imageUrl); + AndroidUtils.openLinkInBrowser((Activity) context, postImage.imageUrl.toString()); break; case SEARCH_ID: List items = new ArrayList<>(); @@ -211,7 +211,7 @@ public class ImageViewerController extends Controller implements ImageViewerPres public void onFloatingMenuItemClicked(FloatingMenu menu, FloatingMenuItem item) { for (ImageSearch imageSearch : ImageSearch.engines) { if (((Integer) item.getId()) == imageSearch.getId()) { - AndroidUtils.openLinkInBrowser((Activity) context, imageSearch.getUrl(presenter.getCurrentPostImage().imageUrl)); + AndroidUtils.openLinkInBrowser((Activity) context, imageSearch.getUrl(presenter.getCurrentPostImage().imageUrl.toString())); break; } } @@ -234,7 +234,7 @@ public class ImageViewerController extends Controller implements ImageViewerPres private void saveShare(boolean share, PostImage postImage) { if (share && ChanSettings.shareUrl.get()) { - AndroidUtils.shareLink(postImage.imageUrl); + AndroidUtils.shareLink(postImage.imageUrl.toString()); } else { ImageSaveTask task = new ImageSaveTask(postImage); task.setShare(share); @@ -373,7 +373,7 @@ public class ImageViewerController extends Controller implements ImageViewerPres } }); - imageLoader.get(postImage.thumbnailUrl, new ImageLoader.ImageListener() { + imageLoader.get(postImage.thumbnailUrl.toString(), new ImageLoader.ImageListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse for preview in transition in ImageViewerController, cannot show correct transition bitmap"); @@ -395,7 +395,7 @@ public class ImageViewerController extends Controller implements ImageViewerPres return; } - imageLoader.get(postImage.thumbnailUrl, new ImageLoader.ImageListener() { + imageLoader.get(postImage.thumbnailUrl.toString(), new ImageLoader.ImageListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "onErrorResponse for preview out transition in ImageViewerController, cannot show correct transition bitmap"); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/MainSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/MainSettingsController.java index 2a19a5d3..318570f1 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/MainSettingsController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/MainSettingsController.java @@ -28,12 +28,12 @@ import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.Toast; -import org.floens.chan.Chan; import org.floens.chan.R; import org.floens.chan.core.database.DatabaseManager; import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.model.Board; import org.floens.chan.core.settings.ChanSettings; +import org.floens.chan.core.site.Sites; import org.floens.chan.ui.activity.StartActivity; import org.floens.chan.ui.helper.HintPopup; import org.floens.chan.ui.helper.RefreshUIMessage; @@ -115,7 +115,8 @@ public class MainSettingsController extends SettingsController implements Toolba populatePreferences(); onWatchEnabledChanged(ChanSettings.watchEnabled.get()); - onPassEnabledChanged(ChanSettings.passLoggedIn()); + // TODO(multi-site) + onPassEnabledChanged(Sites.defaultSite().isLoggedIn()); buildPreferences(); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java index 38db03c8..395c8993 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java @@ -29,7 +29,6 @@ import android.widget.TextView; import org.floens.chan.R; import org.floens.chan.controller.Controller; import org.floens.chan.core.manager.ReplyManager; -import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.site.Site; import org.floens.chan.core.site.Sites; import org.floens.chan.core.site.http.HttpCall; @@ -61,6 +60,8 @@ public class PassSettingsController extends Controller implements View.OnClickLi private EditText inputPin; private TextView authenticated; + private Site site; + public PassSettingsController(Context context) { super(context); } @@ -70,6 +71,9 @@ public class PassSettingsController extends Controller implements View.OnClickLi super.onCreate(); getGraph().inject(this); + // TODO(multi-site) some selector of some sorts + site = Sites.defaultSite(); + navigationItem.setTitle(R.string.settings_screen_pass); view = inflateRes(R.layout.controller_pass); @@ -91,8 +95,9 @@ public class PassSettingsController extends Controller implements View.OnClickLi bottomDescription.setText(Html.fromHtml(getString(R.string.setting_pass_bottom_description))); bottomDescription.setMovementMethod(LinkMovementMethod.getInstance()); - inputToken.setText(ChanSettings.passToken.get()); - inputPin.setText(ChanSettings.passPin.get()); + LoginRequest loginDetails = site.getLoginDetails(); + inputToken.setText(loginDetails.user); + inputPin.setText(loginDetails.pass); // Sanity check if (parentController.view.getWindowToken() == null) { @@ -115,7 +120,7 @@ public class PassSettingsController extends Controller implements View.OnClickLi public void onClick(View v) { if (v == button) { if (loggedIn()) { - ChanSettings.passId.set(""); + deauth(); crossfadeView.toggle(true, true); button.setText(R.string.setting_pass_login); hideError(); @@ -146,7 +151,6 @@ public class PassSettingsController extends Controller implements View.OnClickLi private void authSuccess(LoginResponse response) { crossfadeView.toggle(false, true); button.setText(R.string.setting_pass_logout); - ChanSettings.passId.set(response.token); authenticated.setText(response.message); ((PassSettingControllerListener) previousSiblingController).onPassEnabledChanged(true); } @@ -175,12 +179,14 @@ public class PassSettingsController extends Controller implements View.OnClickLi button.setText(R.string.setting_pass_logging_in); hideError(); - ChanSettings.passToken.set(inputToken.getText().toString()); - ChanSettings.passPin.set(inputPin.getText().toString()); + // TODO(multi-site) + String user = inputToken.getText().toString(); + String pass = inputPin.getText().toString(); + site.login(new LoginRequest(user, pass), this); + } - // TODO(multi-site) some selector of some sorts - Site site = Sites.defaultSite(); - site.login(new LoginRequest(site, ChanSettings.passToken.get(), ChanSettings.passPin.get()), this); + private void deauth() { + site.logout(); } private void showError(String error) { @@ -194,7 +200,7 @@ public class PassSettingsController extends Controller implements View.OnClickLi } private boolean loggedIn() { - return ChanSettings.passId.get().length() > 0; + return site.isLoggedIn(); } public interface PassSettingControllerListener { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/ReportController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/ReportController.java index 44db40e5..c01439da 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/ReportController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/ReportController.java @@ -19,17 +19,13 @@ package org.floens.chan.ui.controller; import android.annotation.SuppressLint; import android.content.Context; -import android.webkit.CookieManager; import android.webkit.WebSettings; import android.webkit.WebView; import org.floens.chan.R; -import org.floens.chan.chan.ChanUrls; import org.floens.chan.controller.Controller; import org.floens.chan.core.model.Post; -import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.site.Site; -import org.floens.chan.core.site.Sites; import org.floens.chan.ui.helper.PostHelper; import okhttp3.HttpUrl; @@ -42,7 +38,6 @@ public class ReportController extends Controller { this.post = post; } - @SuppressWarnings("deprecation") @SuppressLint("SetJavaScriptEnabled") @Override public void onCreate() { @@ -50,25 +45,16 @@ public class ReportController extends Controller { navigationItem.title = context.getString(R.string.report_screen, PostHelper.getTitle(post, null)); Site site = post.board.getSite(); - String url = site.endpoints().report(post); - - if (site == Sites.CHAN4) { - CookieManager cookieManager = CookieManager.getInstance(); - cookieManager.removeAllCookie(); - if (ChanSettings.passLoggedIn()) { - HttpUrl parsed = HttpUrl.parse(url); - String domain = parsed.scheme() + "://" + parsed.host() + "/"; - for (String cookie : ChanUrls.getReportCookies(ChanSettings.passId.get())) { - cookieManager.setCookie(domain, cookie); - } - } - } + HttpUrl url = site.endpoints().report(post); WebView webView = new WebView(context); + + site.requestModifier().modifyWebView(webView); + WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setDomStorageEnabled(true); - webView.loadUrl(url); + webView.loadUrl(url.toString()); view = webView; } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java b/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java index bbca5067..f08c4651 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java @@ -190,10 +190,10 @@ public class WatchNotifier extends Service { List expandedLines = new ArrayList<>(); for (Post postForExpandedLine : postsForExpandedLines) { CharSequence prefix; - if (postForExpandedLine.title.length() <= SUBJECT_LENGTH) { - prefix = postForExpandedLine.title; + if (postForExpandedLine.getTitle().length() <= SUBJECT_LENGTH) { + prefix = postForExpandedLine.getTitle(); } else { - prefix = postForExpandedLine.title.subSequence(0, SUBJECT_LENGTH); + prefix = postForExpandedLine.getTitle().subSequence(0, SUBJECT_LENGTH); } String comment = postForExpandedLine.image != null ? IMAGE_TEXT : ""; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java index 9bea0ecc..7192ca77 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java @@ -129,16 +129,16 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener public boolean onMeasured(View view) { switch (newMode) { case LOWRES: - setThumbnail(postImage.thumbnailUrl); + setThumbnail(postImage.thumbnailUrl.toString()); break; case BIGIMAGE: - setBigImage(postImage.imageUrl); + setBigImage(postImage.imageUrl.toString()); break; case GIF: - setGif(postImage.imageUrl); + setGif(postImage.imageUrl.toString()); break; case MOVIE: - setVideo(postImage.imageUrl); + setVideo(postImage.imageUrl.toString()); break; } return true; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/PostImageThumbnailView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/PostImageThumbnailView.java index 5e48232f..87e111d5 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/view/PostImageThumbnailView.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/view/PostImageThumbnailView.java @@ -52,7 +52,7 @@ public class PostImageThumbnailView extends ThumbnailView { this.postImage = postImage; if (postImage != null) { - setUrl(postImage.thumbnailUrl, width, height); + setUrl(postImage.thumbnailUrl.toString(), width, height); } else { setUrl(null, width, height); } diff --git a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java index 1f00ff5d..a6b7c86a 100644 --- a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java +++ b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java @@ -93,6 +93,10 @@ public class AndroidUtils { return PreferenceManager.getDefaultSharedPreferences(Chan.getInstance()); } + public static SharedPreferences getPreferences(String name) { + return Chan.getInstance().getSharedPreferences(name, Context.MODE_PRIVATE); + } + /** * Tries to open an app that can open the specified URL.
* If this app will open the link then show a chooser to the user without this app.