Skip to content

Commit

Permalink
Add support for Fragments (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
wangdaliu authored May 24, 2022
1 parent ea642ae commit 09714fb
Show file tree
Hide file tree
Showing 31 changed files with 1,879 additions and 437 deletions.
79 changes: 79 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,85 @@ final AffirmTrack affirmTrack = AffirmTrack.builder()
Affirm.trackOrderConfirmed(MainActivity.this, trackModel());
```
## Fragment supports
We also support using fragment directly, only need to pass a ViewGroup id, we will put the `AffirmFragment` in this specified view.
- Checkout
```java
// In your activity/fragment, you need to implement Affirm.CheckoutCallbacks
Affirm.startCheckout(this, R.id.container, checkoutModel(), null, 10, false);
// - Affirm.CheckoutCallbacks
@Override
public void onAffirmCheckoutSuccess(@NonNull String token) {
Toast.makeText(this, "Checkout token: " + token, Toast.LENGTH_LONG).show();
}
@Override
public void onAffirmCheckoutCancelled() {
Toast.makeText(this, "Checkout Cancelled", Toast.LENGTH_LONG).show();
}
@Override
public void onAffirmCheckoutError(@Nullable String message) {
Toast.makeText(this, "Checkout Error: " + message, Toast.LENGTH_LONG).show();
}
```
- VCN checkout
```java
// In your activity/fragment, you need to implement Affirm.VcnCheckoutCallbacks
Affirm.startCheckout(this, R.id.container, checkoutModel(), null, 10, true);
// - Affirm.VcnCheckoutCallbacks
@Override
public void onAffirmVcnCheckoutCancelled() {
Toast.makeText(this, "Vcn Checkout Cancelled", Toast.LENGTH_LONG).show();
}
@Override
public void onAffirmVcnCheckoutCancelledReason(@NonNull VcnReason vcnReason) {
Toast.makeText(this, "Vcn Checkout Cancelled: " + vcnReason.toString(), Toast.LENGTH_LONG).show();
}
@Override
public void onAffirmVcnCheckoutError(@Nullable String message) {
Toast.makeText(this, "Vcn Checkout Error: " + message, Toast.LENGTH_LONG).show();
}
@Override
public void onAffirmVcnCheckoutSuccess(@NonNull CardDetails cardDetails) {
Toast.makeText(this, "Vcn Checkout Card: " + cardDetails.toString(), Toast.LENGTH_LONG).show();
}
```
- Promotion
```java
AffirmPromotionButton affirmPromotionButton = findViewById(R.id.promo);
Affirm.configureWithAmount(this, R.id.container, affirmPromotionButton, null, PromoPageType.PRODUCT, PRICE, true, null);
```
- Site modal
```java
// In your activity/fragment, you need to implement Affirm.PrequalCallbacks
Affirm.showSiteModal(this, R.id.container, null, "5LNMQ33SEUYHLNUC");
@Override
public void onAffirmPrequalError(@Nullable String message) {
Toast.makeText(this, "Prequal Error: " + message, Toast.LENGTH_LONG).show();
}
```
- Product modal
```java
// In your activity/fragment, you need to implement Affirm.PrequalCallbacks
Affirm.showProductModal(this, R.id.container, PRICE, null, PromoPageType.PRODUCT, null)
@Override
public void onAffirmPrequalError(@Nullable String message) {
Toast.makeText(this, "Prequal Error: " + message, Toast.LENGTH_LONG).show();
}
```
- Since there is no callback, it will return success after 10 seconds timeout
- We will replace using the HTTP API after the API is done
Expand Down
341 changes: 320 additions & 21 deletions affirm/src/main/java/com/affirm/android/Affirm.java

Large diffs are not rendered by default.

73 changes: 41 additions & 32 deletions affirm/src/main/java/com/affirm/android/AffirmActivity.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
package com.affirm.android;

import static com.affirm.android.Affirm.RESULT_ERROR;
import static com.affirm.android.AffirmConstants.CHECKOUT_ERROR;
import static com.affirm.android.AffirmConstants.CHECKOUT_TOKEN;
import static com.affirm.android.AffirmConstants.CREDIT_DETAILS;
import static com.affirm.android.AffirmConstants.PREQUAL_ERROR;
import static com.affirm.android.AffirmConstants.VCN_REASON;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;

abstract class AffirmActivity extends AppCompatActivity implements AffirmWebChromeClient.Callbacks {
import com.affirm.android.model.CardDetails;
import com.affirm.android.model.VcnReason;

AffirmWebView webView;
View progressIndicator;
abstract class AffirmActivity extends AppCompatActivity {

static void startForResult(@NonNull Activity originalActivity,
@NonNull Intent intent,
Expand All @@ -28,39 +33,43 @@ static void startForResult(@NonNull Fragment originalFragment,
originalFragment.startActivityForResult(intent, requestCode);
}

abstract void initViews();

abstract void beforeOnCreate();

abstract void initData(@Nullable Bundle savedInstanceState);

abstract void onAttached();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
beforeOnCreate();
super.onCreate(savedInstanceState);

setContentView(R.layout.affirm_activity_webview);
webView = findViewById(R.id.webview);
progressIndicator = findViewById(R.id.progressIndicator);
protected void finishWithError(@Nullable String error) {
final Intent intent = new Intent();
intent.putExtra(CHECKOUT_ERROR, error);
setResult(RESULT_ERROR, intent);
finish();
}

initViews();
protected void finishWithToken(String token) {
final Intent intent = new Intent();
intent.putExtra(CHECKOUT_TOKEN, token);
setResult(Activity.RESULT_OK, intent);
finish();
}

initData(savedInstanceState);
protected void finishWithCancellation() {
setResult(Activity.RESULT_CANCELED);
finish();
}

onAttached();
protected void finishWithCardDetail(@NonNull CardDetails cardDetails) {
final Intent intent = new Intent();
intent.putExtra(CREDIT_DETAILS, cardDetails);
setResult(Activity.RESULT_OK, intent);
finish();
}

@Override
protected void onDestroy() {
webView.destroyWebView();
webView = null;
super.onDestroy();
protected void finishWithVcnReason(@NonNull VcnReason vcnReason) {
final Intent intent = new Intent();
intent.putExtra(VCN_REASON, vcnReason);
setResult(Activity.RESULT_CANCELED, intent);
finish();
}

@Override
public void chromeLoadCompleted() {
progressIndicator.setVisibility(View.GONE);
protected void finishWithPrequalError(@Nullable String error) {
final Intent intent = new Intent();
intent.putExtra(PREQUAL_ERROR, error);
setResult(RESULT_ERROR, intent);
finish();
}
}
6 changes: 4 additions & 2 deletions affirm/src/main/java/com/affirm/android/AffirmClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ public void onResponse(@NotNull Call call, @NotNull Response response) {
);
} catch (JsonSyntaxException | IOException e) {
handleErrorResponse(
new APIException("Some error occurred while parsing the "
+ "promo response", e), listener
new APIException("Some error occurred while parsing response",
e),
listener

);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ static String getProductionInvalidCheckoutRedirectUrl() {
static final String CHECKOUT_TOKEN = "checkout_token";
static final String CHECKOUT_ERROR = "checkout_error";
static final String CHECKOUT_EXTRA = "checkout_extra";
static final String CHECKOUT_RECEIVE_REASON_CODES = "checkout_receive_reason_codes";
static final String CHECKOUT_CAAS_EXTRA = "checkout_caas_extra";
static final String CHECKOUT_MONEY = "checkout_money";
static final String CHECKOUT_CARD_AUTH_WINDOW = "checkout_card_auth_window";
Expand Down
82 changes: 82 additions & 0 deletions affirm/src/main/java/com/affirm/android/AffirmFragment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.affirm.android;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

abstract class AffirmFragment extends Fragment implements AffirmWebChromeClient.Callbacks {

protected static final String TAG_PREFIX = "AffirmFragment";

AffirmWebView webView;
private View progressIndicator;

abstract void initViews();

abstract void onAttached();

protected static void addFragment(FragmentManager fragmentManager, @IdRes int containerViewId,
@NonNull Fragment fragment, @NonNull String tag) {
fragmentManager
.beginTransaction()
.add(containerViewId, fragment, tag)
.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}

protected void removeFragment(@NonNull String tag) {
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager == null) {
AffirmLog.d("The fragment is getting detached from the Activity");
return;
}
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment != null) {
fragmentManager.beginTransaction().remove(fragment).commit();
}
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.affirm_fragment_webview, container, false);
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);

webView = view.findViewById(R.id.webview);
progressIndicator = view.findViewById(R.id.progressIndicator);

AffirmUtils.debuggableWebView(getContext());
initViews();
onAttached();
}

@Override
public void onDestroy() {
webView.destroyWebView();
webView = null;
super.onDestroy();
}

@Override
public void chromeLoadCompleted() {
progressIndicator.setVisibility(View.GONE);
}
}
6 changes: 4 additions & 2 deletions affirm/src/main/java/com/affirm/android/AffirmTrackView.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,14 @@ public void run() {

private String initialHtml() {
String html;
InputStream ins = null;
try {
final InputStream ins =
getResources().openRawResource(R.raw.affirm_track_order_confirmed);
ins = getResources().openRawResource(R.raw.affirm_track_order_confirmed);
html = AffirmUtils.readInputStream(ins);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
AffirmUtils.closeInputStream(ins);
}
final String fullPath = HTTPS_PROTOCOL + AffirmPlugins.get().baseJsUrl() + JS_PATH;

Expand Down
10 changes: 10 additions & 0 deletions affirm/src/main/java/com/affirm/android/AffirmUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ static String readInputStream(@NonNull InputStream inputStream) throws IOExcepti
return total.toString();
}

static void closeInputStream(@Nullable InputStream inputStream) {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
AffirmLog.e("Failed to close InputStream!", e);
}
}
}

static String replacePlaceholders(@NonNull String text, @NonNull Map<String, String> map) {
for (Object o : map.entrySet()) {
Map.Entry pair = (Map.Entry) o;
Expand Down
Loading

0 comments on commit 09714fb

Please sign in to comment.