diff --git a/Clover/app/src/main/assets/captcha/captcha1.html b/Clover/app/src/main/assets/captcha/captcha1.html deleted file mode 100644 index e6bfd441..00000000 --- a/Clover/app/src/main/assets/captcha/captcha1.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - -
-
- -
- - - - - diff --git a/Clover/app/src/main/assets/captcha/captcha_legacy.html b/Clover/app/src/main/assets/captcha/captcha_legacy.html new file mode 100644 index 00000000..fe370867 --- /dev/null +++ b/Clover/app/src/main/assets/captcha/captcha_legacy.html @@ -0,0 +1,40 @@ +
+
+ +
+ + + 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 a14384a2..c0d6ed77 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 @@ -36,7 +36,8 @@ import org.floens.chan.core.model.SavedReply; import org.floens.chan.core.pool.LoadablePool; import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.ui.helper.ImagePickDelegate; -import org.floens.chan.ui.layout.CaptchaLayout; +import org.floens.chan.ui.layout.CaptchaCallback; +import org.floens.chan.ui.layout.CaptchaLayoutInterface; import java.io.File; import java.nio.charset.Charset; @@ -47,7 +48,7 @@ import static org.floens.chan.utils.AndroidUtils.getReadableFileSize; import static org.floens.chan.utils.AndroidUtils.getRes; import static org.floens.chan.utils.AndroidUtils.getString; -public class ReplyPresenter implements ReplyManager.HttpCallback, CaptchaLayout.CaptchaCallback, ImagePickDelegate.ImagePickCallback { +public class ReplyPresenter implements ReplyManager.HttpCallback, CaptchaCallback, ImagePickDelegate.ImagePickCallback { public enum Page { INPUT, CAPTCHA, @@ -238,11 +239,11 @@ public class ReplyPresenter implements ReplyManager.HttpCallback, } @Override - public void captchaLoaded(CaptchaLayout captchaLayout) { + public void captchaLoaded(CaptchaLayoutInterface captchaLayout) { } @Override - public void captchaEntered(CaptchaLayout captchaLayout, String challenge, String response) { + public void captchaEntered(CaptchaLayoutInterface captchaLayout, String challenge, String response) { draft.captchaChallenge = challenge; draft.captchaResponse = response; captchaLayout.reset(); @@ -402,7 +403,7 @@ public class ReplyPresenter implements ReplyManager.HttpCallback, void setPage(Page page, boolean animate); - void initCaptcha(String baseUrl, String siteKey, CaptchaLayout.CaptchaCallback callback); + void initCaptcha(String baseUrl, String siteKey, CaptchaCallback callback); void resetCaptcha(); 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 f7619db2..cb58d4dc 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 @@ -132,7 +132,7 @@ public class ChanSettings { postDefaultName = new StringSetting(p, "preference_default_name", ""); postPinThread = new BooleanSetting(p, "preference_pin_on_post", false); - postNewCaptcha = new BooleanSetting(p, "preference_new_captcha", true); + postNewCaptcha = new BooleanSetting(p, "preference_new_captcha", false); developer = new BooleanSetting(p, "preference_developer", false); 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 cbbb9c1c..7b14de00 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 @@ -33,6 +33,7 @@ import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.ui.theme.Theme; import org.floens.chan.ui.theme.ThemeHelper; import org.floens.chan.ui.view.FastTextView; +import org.floens.chan.ui.view.FixedRatioThumbnailView; import org.floens.chan.ui.view.FloatingMenu; import org.floens.chan.ui.view.FloatingMenuItem; import org.floens.chan.ui.view.ThumbnailView; @@ -50,7 +51,7 @@ public class CardPostCell extends CardView implements PostCellInterface, View.On private Post post; private PostCellInterface.PostCellCallback callback; - private ThumbnailView thumbnailView; + private FixedRatioThumbnailView thumbnailView; private TextView title; private FastTextView comment; private TextView replies; @@ -73,7 +74,8 @@ public class CardPostCell extends CardView implements PostCellInterface, View.On protected void onFinishInflate() { super.onFinishInflate(); - thumbnailView = (ThumbnailView) findViewById(R.id.thumbnail); + thumbnailView = (FixedRatioThumbnailView) findViewById(R.id.thumbnail); + thumbnailView.setRatio(16f / 9f); thumbnailView.setOnClickListener(this); title = (TextView) findViewById(R.id.title); comment = (FastTextView) findViewById(R.id.comment); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java index ce840b3e..c4be8e0f 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java @@ -45,6 +45,7 @@ public class AdvancedSettingsController extends SettingsController { private boolean needRestart; private LinkSettingView saveLocation; + private SettingView newCaptcha; private SettingView forcePhoneLayoutSetting; private SettingView enableReplyFab; private SettingView postFullDate; @@ -85,7 +86,7 @@ public class AdvancedSettingsController extends SettingsController { public void onPreferenceChange(SettingView item) { super.onPreferenceChange(item); - if (item == forcePhoneLayoutSetting || item == enableReplyFab) { + if (item == forcePhoneLayoutSetting || item == enableReplyFab || item == newCaptcha) { needRestart = true; } @@ -118,7 +119,7 @@ public class AdvancedSettingsController extends SettingsController { })); setSaveLocationDescription(); - settings.add(new BooleanSettingView(this, ChanSettings.postNewCaptcha, string(R.string.setting_use_new_captcha), string(R.string.setting_use_new_captcha_description))); + newCaptcha = settings.add(new BooleanSettingView(this, ChanSettings.postNewCaptcha, string(R.string.setting_use_new_captcha), string(R.string.setting_use_new_captcha_description))); settings.add(new BooleanSettingView(this, ChanSettings.saveOriginalFilename, string(R.string.setting_save_original_filename), null)); settings.add(new BooleanSettingView(this, ChanSettings.shareUrl, string(R.string.setting_share_url), string(R.string.setting_share_url_description))); settings.add(new BooleanSettingView(this, ChanSettings.networkHttps, string(R.string.setting_network_https), string(R.string.setting_network_https_description))); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaCallback.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaCallback.java new file mode 100644 index 00000000..d2c60065 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaCallback.java @@ -0,0 +1,7 @@ +package org.floens.chan.ui.layout; + +public interface CaptchaCallback { + void captchaLoaded(CaptchaLayoutInterface captchaLayout); + + void captchaEntered(CaptchaLayoutInterface captchaLayout, String challenge, String response); +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayout.java index d6fa9ae0..52607ee6 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayout.java @@ -36,7 +36,7 @@ import org.floens.chan.ChanBuild; import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.IOUtils; -public class CaptchaLayout extends WebView { +public class CaptchaLayout extends WebView implements CaptchaLayoutInterface { private static final String TAG = "CaptchaLayout"; private CaptchaCallback callback; @@ -44,7 +44,6 @@ public class CaptchaLayout extends WebView { private String baseUrl; private String siteKey; private boolean lightTheme; - private boolean useNew; public CaptchaLayout(Context context) { super(context); @@ -59,12 +58,11 @@ public class CaptchaLayout extends WebView { } @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"}) - public void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, boolean useNew, CaptchaCallback callback) { + public void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, CaptchaCallback callback) { this.callback = callback; this.baseUrl = baseUrl; this.siteKey = siteKey; this.lightTheme = lightTheme; - this.useNew = useNew; WebSettings settings = getSettings(); settings.setJavaScriptEnabled(true); @@ -98,11 +96,13 @@ public class CaptchaLayout extends WebView { } } - public void load() { - if (!loaded) { + public void reset() { + if (loaded) { + loadUrl("javascript:grecaptcha.reset()"); + } else { loaded = true; - String html = IOUtils.assetAsString(getContext(), useNew ? "captcha/captcha.html" : "captcha/captcha1.html"); + String html = IOUtils.assetAsString(getContext(), "captcha/captcha.html"); html = html.replace("__site_key__", siteKey); html = html.replace("__theme__", lightTheme ? "light" : "dark"); @@ -110,18 +110,6 @@ public class CaptchaLayout extends WebView { } } - public void reset() { - if (loaded) { - if (useNew) { - loadUrl("javascript:grecaptcha.reset()"); - } else { - loadUrl("javascript:Recaptcha.reload()"); - } - } else { - load(); - } - } - private void onCaptchaLoaded() { callback.captchaLoaded(this); } @@ -134,12 +122,6 @@ public class CaptchaLayout extends WebView { } } - public interface CaptchaCallback { - void captchaLoaded(CaptchaLayout captchaLayout); - - void captchaEntered(CaptchaLayout captchaLayout, String challenge, String response); - } - public static class CaptchaInterface { private final CaptchaLayout layout; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayoutInterface.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayoutInterface.java new file mode 100644 index 00000000..d449469e --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayoutInterface.java @@ -0,0 +1,7 @@ +package org.floens.chan.ui.layout; + +public interface CaptchaLayoutInterface { + void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, CaptchaCallback callback); + + void reset(); +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/LegacyCaptchaLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/LegacyCaptchaLayout.java new file mode 100644 index 00000000..47b17e40 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/LegacyCaptchaLayout.java @@ -0,0 +1,133 @@ +package org.floens.chan.ui.layout; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Build; +import android.util.AttributeSet; +import android.view.View; +import android.webkit.JavascriptInterface; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import org.floens.chan.ChanBuild; +import org.floens.chan.R; +import org.floens.chan.ui.view.FixedRatioThumbnailView; +import org.floens.chan.utils.AndroidUtils; +import org.floens.chan.utils.IOUtils; + +import static org.floens.chan.ui.theme.ThemeHelper.theme; +import static org.floens.chan.utils.AndroidUtils.setRoundItemBackground; + +public class LegacyCaptchaLayout extends LinearLayout implements CaptchaLayoutInterface, View.OnClickListener { + private FixedRatioThumbnailView image; + private EditText input; + private ImageView submit; + + private WebView internalWebView; + + private String baseUrl; + private String siteKey; + private CaptchaCallback callback; + + private String challenge; + + + public LegacyCaptchaLayout(Context context) { + super(context); + } + + public LegacyCaptchaLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public LegacyCaptchaLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"}) + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + image = (FixedRatioThumbnailView) findViewById(R.id.image); + image.setRatio(300f / 57f); + image.setOnClickListener(this); + input = (EditText) findViewById(R.id.input); + submit = (ImageView) findViewById(R.id.submit); + theme().sendDrawable.apply(submit); + setRoundItemBackground(submit); + submit.setOnClickListener(this); + + // This captcha layout uses a webview in the background + // Because the script changed significantly we can't just load the image straight up from the challenge data anymore. + // Now we load a skeleton page in the background, and wait until both the image and challenge key are loaded, + // then the onCaptchaLoaded is called through the javascript interface. + + internalWebView = new WebView(getContext()); + internalWebView.setWebChromeClient(new WebChromeClient()); + internalWebView.setWebViewClient(new WebViewClient()); + + WebSettings settings = internalWebView.getSettings(); + settings.setJavaScriptEnabled(true); + + internalWebView.addJavascriptInterface(new CaptchaInterface(this), "CaptchaCallback"); + + //noinspection PointlessBooleanExpression + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && ChanBuild.DEVELOPER_MODE) { + WebView.setWebContentsDebuggingEnabled(true); + } + } + + @Override + public void onClick(View v) { + if (v == submit) { + callback.captchaEntered(this, challenge, input.getText().toString()); + } else if (v == image) { + reset(); + } + } + + @Override + public void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, CaptchaCallback callback) { + this.baseUrl = baseUrl; + this.siteKey = siteKey; + this.callback = callback; + } + + @Override + public void reset() { + input.setText(""); + String html = IOUtils.assetAsString(getContext(), "captcha/captcha_legacy.html"); + html = html.replace("__site_key__", siteKey); + internalWebView.loadDataWithBaseURL(baseUrl, html, "text/html", "UTF-8", null); + image.setUrl(null, 0, 0); + } + + private void onCaptchaLoaded(final String imageUrl, final String challenge) { + this.challenge = challenge; + image.setUrl(imageUrl, 300, 57); + } + + public static class CaptchaInterface { + private final LegacyCaptchaLayout layout; + + public CaptchaInterface(LegacyCaptchaLayout layout) { + this.layout = layout; + } + + @JavascriptInterface + public void onCaptchaLoaded(final String imageUrl, final String challenge) { + AndroidUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + layout.onCaptchaLoaded(imageUrl, challenge); + } + }); + } + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java index d5472db1..8448e8e2 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java @@ -23,6 +23,7 @@ import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; @@ -61,7 +62,7 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima private ReplyLayoutCallback callback; private View replyInputLayout; - private CaptchaLayout captchaLayout; + private CaptchaLayoutInterface captchaLayout; private boolean openingName; private boolean blockSelectionChange = false; @@ -161,11 +162,13 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima @Override public LayoutParams getLayoutParamsForView(View view) { - if (view == replyInputLayout) { + if (view == replyInputLayout || (view == captchaLayout && captchaLayout instanceof LegacyCaptchaLayout)) { return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + } else if (view == captchaLayout && captchaLayout instanceof CaptchaLayout) { + return new LayoutParams(LayoutParams.MATCH_PARENT, dp(300)); } else { - // Captcha and the loadbar - return new LayoutParams(LayoutParams.MATCH_PARENT, getResources().getDimensionPixelSize(R.dimen.reply_height_loading)); + // Loadbar + return new LayoutParams(LayoutParams.MATCH_PARENT, dp(100)); } } @@ -193,6 +196,11 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima }*/ } + @Override + public boolean onTouchEvent(MotionEvent event) { + return true; + } + @Override public void setPage(ReplyPresenter.Page page, boolean animate) { setAnimateLayout(animate, true); @@ -205,10 +213,14 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima break; case CAPTCHA: if (captchaLayout == null) { - captchaLayout = new CaptchaLayout(getContext()); + if (ChanSettings.postNewCaptcha.get()) { + captchaLayout = new CaptchaLayout(getContext()); + } else { + captchaLayout = (CaptchaLayoutInterface) LayoutInflater.from(getContext()).inflate(R.layout.layout_captcha_legacy, this, false); + } } - setView(captchaLayout); + setView((View) captchaLayout); AndroidUtils.hideKeyboard(this); break; @@ -216,9 +228,9 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima } @Override - public void initCaptcha(String baseUrl, String siteKey, CaptchaLayout.CaptchaCallback callback) { - captchaLayout.initCaptcha(baseUrl, siteKey, ThemeHelper.getInstance().getTheme().isLightTheme, ChanSettings.postNewCaptcha.get(), callback); - captchaLayout.load(); + public void initCaptcha(String baseUrl, String siteKey, CaptchaCallback callback) { + captchaLayout.initCaptcha(baseUrl, siteKey, ThemeHelper.getInstance().getTheme().isLightTheme, callback); + captchaLayout.reset(); } @Override diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/FixedRatioThumbnailView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/FixedRatioThumbnailView.java index a3fd2d0e..6e402190 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/view/FixedRatioThumbnailView.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/view/FixedRatioThumbnailView.java @@ -21,6 +21,8 @@ import android.content.Context; import android.util.AttributeSet; public class FixedRatioThumbnailView extends ThumbnailView { + private float ratio; + public FixedRatioThumbnailView(Context context) { super(context); } @@ -33,13 +35,17 @@ public class FixedRatioThumbnailView extends ThumbnailView { super(context, attrs, defStyleAttr); } + public void setRatio(float ratio) { + this.ratio = ratio; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY && (heightMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.AT_MOST)) { int width = MeasureSpec.getSize(widthMeasureSpec); - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec((int) (width / 16f * 9f), MeasureSpec.EXACTLY)); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec((int) (width / ratio), MeasureSpec.EXACTLY)); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } diff --git a/Clover/app/src/main/res/layout/layout_captcha_legacy.xml b/Clover/app/src/main/res/layout/layout_captcha_legacy.xml new file mode 100644 index 00000000..2f6546a7 --- /dev/null +++ b/Clover/app/src/main/res/layout/layout_captcha_legacy.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/Clover/app/src/main/res/values-sw600dp/dimens.xml b/Clover/app/src/main/res/values-sw600dp/dimens.xml index b96e43bd..455632f4 100644 --- a/Clover/app/src/main/res/values-sw600dp/dimens.xml +++ b/Clover/app/src/main/res/values-sw600dp/dimens.xml @@ -21,7 +21,5 @@ along with this program. If not, see . 105dp 240dp - 400dp - 100dp diff --git a/Clover/app/src/main/res/values/dimens.xml b/Clover/app/src/main/res/values/dimens.xml index 86687ec6..ba380a58 100644 --- a/Clover/app/src/main/res/values/dimens.xml +++ b/Clover/app/src/main/res/values/dimens.xml @@ -23,7 +23,5 @@ along with this program. If not, see . 120dp 200dp - 250dp - 72dp diff --git a/Clover/app/src/main/res/values/strings.xml b/Clover/app/src/main/res/values/strings.xml index a83c614a..5afd2baa 100644 --- a/Clover/app/src/main/res/values/strings.xml +++ b/Clover/app/src/main/res/values/strings.xml @@ -237,6 +237,7 @@ along with this program. If not, see . Submit Error posting Post successful + Type the text Delete your post? Deleting post… @@ -332,7 +333,7 @@ along with this program. If not, see . Error creating save folder Choose Use the new captcha - Disable to fallback to the old captcha (EXPERIMENTAL). + Enable to use the newer recaptcha. Save original filename Share url to image Share the url to the image instead of the image itself @@ -409,8 +410,3 @@ along with this program. If not, see . Themes - - - - -