diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9bb84c17..b8976c23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,6 @@ jobs: with: java-version: '1.8' - name: Assemble & Test - run: gradle build --stacktrace + run: ./gradlew build --stacktrace - name: JitPack Test - run: gradle publishReleasePublicationToMavenLocal + run: ./gradlew publishReleasePublicationToMavenLocal diff --git a/README.md b/README.md index 1f743ad0..0669f9ba 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ final HCaptchaConfig config = HCaptchaConfig.builder() .apiEndpoint("https://hcaptcha.com/1/api.js") .locale("ro") .size(HCaptchaSize.INVISIBLE) + .loading(false) .theme(HCaptchaTheme.DARK) .build(); HCaptcha.getClient(this).verifyWithHCaptcha(config)...; @@ -89,6 +90,7 @@ HCaptcha.getClient(this).verifyWithHCaptcha(config)...; |`reportapi`|String|No|-|See Enterprise docs.| |`assethost`|String|No|-|See Enterprise docs.| |`imghost`|String|No|-|See Enterprise docs.| +|`loading`|Boolean|No|True|Show or hide the loading dialog.| #### Error handling diff --git a/build.gradle b/build.gradle index e5f66cc7..60279d70 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath "com.android.tools.build:gradle:4.0.2" + classpath 'com.android.tools.build:gradle:4.1.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/example-app/src/main/java/com/hcaptcha/example/MainActivity.java b/example-app/src/main/java/com/hcaptcha/example/MainActivity.java index b3c1b8b6..34892484 100644 --- a/example-app/src/main/java/com/hcaptcha/example/MainActivity.java +++ b/example-app/src/main/java/com/hcaptcha/example/MainActivity.java @@ -57,6 +57,7 @@ public void onClickHCaptcha(final HCaptchaSize hCaptchaSize) { .siteKey(YOUR_API_SITE_KEY) .apiEndpoint("https://hcaptcha.com/1/api.js") .size(hCaptchaSize) + .loading(true) .build(); HCaptcha.getClient(this).verifyWithHCaptcha(config) .addOnSuccessListener(new OnSuccessListener() { diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/sdk/build.gradle b/sdk/build.gradle index 03aa2e3f..19868e2e 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -12,11 +12,11 @@ android { // See https://developer.android.com/studio/publish/versioning // versionCode must be integer and be incremented by one for every new update // android system uses this to prevent downgrades - versionCode 5 + versionCode 6 // version number visible to the user // should follow semantic versioning (See https://semver.org) - versionName "1.0.3" + versionName "1.1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" diff --git a/sdk/src/main/java/com/hcaptcha/sdk/HCaptchaConfig.java b/sdk/src/main/java/com/hcaptcha/sdk/HCaptchaConfig.java index 5d6d5012..a7eb56f0 100644 --- a/sdk/src/main/java/com/hcaptcha/sdk/HCaptchaConfig.java +++ b/sdk/src/main/java/com/hcaptcha/sdk/HCaptchaConfig.java @@ -28,6 +28,12 @@ public class HCaptchaConfig implements Serializable { @Builder.Default private Boolean sentry = true; + /** + * Show / Hide loading dialog. + */ + @Builder.Default + private Boolean loading = true; + /** * Custom supplied challenge data. */ diff --git a/sdk/src/main/java/com/hcaptcha/sdk/HCaptchaDialogFragment.java b/sdk/src/main/java/com/hcaptcha/sdk/HCaptchaDialogFragment.java index 1e670a34..fefb901a 100644 --- a/sdk/src/main/java/com/hcaptcha/sdk/HCaptchaDialogFragment.java +++ b/sdk/src/main/java/com/hcaptcha/sdk/HCaptchaDialogFragment.java @@ -9,9 +9,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; +import android.view.*; import android.webkit.*; import android.widget.LinearLayout; import androidx.annotation.NonNull; @@ -49,6 +47,8 @@ public class HCaptchaDialogFragment extends DialogFragment implements private HCaptchaJSInterface hCaptchaJsInterface; + private boolean showLoader; + private HCaptchaDialogListener hCaptchaDialogListener; private View rootView; @@ -90,6 +90,7 @@ public void onCreate(Bundle savedInstanceState) { } final HCaptchaConfig hCaptchaConfig = (HCaptchaConfig) getArguments().getSerializable(KEY_CONFIG); this.hCaptchaJsInterface = new HCaptchaJSInterface(hCaptchaConfig, this, this, this); + this.showLoader = hCaptchaConfig.getLoading(); setStyle(STYLE_NO_FRAME, R.style.HCaptchaDialogTheme); } @@ -97,6 +98,7 @@ public void onCreate(Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.hcaptcha_fragment, container, false); loadingContainer = rootView.findViewById(R.id.loadingContainer); + loadingContainer.setVisibility(showLoader ? View.VISIBLE : View.GONE); webView = rootView.findViewById(R.id.webView); setupWebView(webView); return rootView; @@ -121,7 +123,12 @@ public void onStart() { super.onStart(); final Dialog dialog = getDialog(); if (dialog != null) { - getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + final Window window = dialog.getWindow(); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + if (!showLoader) { + // Remove dialog shadow to appear completely invisible + window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + } } } @@ -155,7 +162,15 @@ public void onLoaded() { handler.post(new Runnable() { @Override public void run() { - loadingContainer.animate().alpha(0.0f).setDuration(200); + if (showLoader) { + loadingContainer.animate().alpha(0.0f).setDuration(200); + } else { + // Add back dialog shadow in case the checkbox or challenge is shown + final Dialog dialog = getDialog(); + if (dialog != null) { + dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + } + } } }); } diff --git a/sdk/src/test/java/com/hcaptcha/sdk/HCaptchaJSInterfaceTest.java b/sdk/src/test/java/com/hcaptcha/sdk/HCaptchaJSInterfaceTest.java index 894016e7..96737d29 100644 --- a/sdk/src/test/java/com/hcaptcha/sdk/HCaptchaJSInterfaceTest.java +++ b/sdk/src/test/java/com/hcaptcha/sdk/HCaptchaJSInterfaceTest.java @@ -51,7 +51,7 @@ public void full_config_serialization() throws JsonProcessingException { .reportapi("https://example.com/reportapi") .build(); final HCaptchaJSInterface HCaptchaJsInterface = new HCaptchaJSInterface(config, null, null, null); - assertEquals("{\"siteKey\":\"0000-1111-2222-3333\",\"sentry\":true,\"rqdata\":\"custom rqdata\",\"apiEndpoint\":\"127.0.0.1/api.js\",\"endpoint\":\"https://example.com/endpoint\",\"reportapi\":\"https://example.com/reportapi\",\"assethost\":\"https://example.com/assethost\",\"imghost\":\"https://example.com/imghost\",\"locale\":\"ro\",\"size\":\"normal\",\"theme\":\"dark\"}", + assertEquals("{\"siteKey\":\"0000-1111-2222-3333\",\"sentry\":true,\"loading\":true,\"rqdata\":\"custom rqdata\",\"apiEndpoint\":\"127.0.0.1/api.js\",\"endpoint\":\"https://example.com/endpoint\",\"reportapi\":\"https://example.com/reportapi\",\"assethost\":\"https://example.com/assethost\",\"imghost\":\"https://example.com/imghost\",\"locale\":\"ro\",\"size\":\"normal\",\"theme\":\"dark\"}", HCaptchaJsInterface.getConfig()); } @@ -65,7 +65,7 @@ public void subset_config_serialization() throws JsonProcessingException { .rqdata("custom rqdata") .build(); final HCaptchaJSInterface HCaptchaJsInterface = new HCaptchaJSInterface(config, null, null, null); - assertEquals("{\"siteKey\":\"0000-1111-2222-3333\",\"sentry\":true,\"rqdata\":\"custom rqdata\",\"apiEndpoint\":\"https://hcaptcha.com/1/api.js\",\"endpoint\":null,\"reportapi\":null,\"assethost\":null,\"imghost\":null,\"locale\":\"ro\",\"size\":\"normal\",\"theme\":\"dark\"}", + assertEquals("{\"siteKey\":\"0000-1111-2222-3333\",\"sentry\":true,\"loading\":true,\"rqdata\":\"custom rqdata\",\"apiEndpoint\":\"https://hcaptcha.com/1/api.js\",\"endpoint\":null,\"reportapi\":null,\"assethost\":null,\"imghost\":null,\"locale\":\"ro\",\"size\":\"normal\",\"theme\":\"dark\"}", HCaptchaJsInterface.getConfig()); }