diff --git a/android/brave_java_sources.gni b/android/brave_java_sources.gni index 2d71e0edc4d..406c3716bc2 100644 --- a/android/brave_java_sources.gni +++ b/android/brave_java_sources.gni @@ -32,7 +32,7 @@ brave_java_sources = [ "../../brave/android/java/org/chromium/chrome/browser/BraveRewardsVerifyWalletActivity.java", "../../brave/android/java/org/chromium/chrome/browser/BraveSyncInformers.java", "../../brave/android/java/org/chromium/chrome/browser/BraveSyncWorker.java", - "../../brave/android/java/org/chromium/chrome/browser/BraveUphold.java", + "../../brave/android/java/org/chromium/chrome/browser/BraveWalletProvider.java", "../../brave/android/java/org/chromium/chrome/browser/CrossPromotionalModalDialogFragment.java", "../../brave/android/java/org/chromium/chrome/browser/DormantUsersEngagementDialogFragment.java", "../../brave/android/java/org/chromium/chrome/browser/InternetConnection.java", diff --git a/android/java/org/chromium/chrome/browser/BraveRewardsBalance.java b/android/java/org/chromium/chrome/browser/BraveRewardsBalance.java index 70ea5eb0cf7..09d4744e850 100644 --- a/android/java/org/chromium/chrome/browser/BraveRewardsBalance.java +++ b/android/java/org/chromium/chrome/browser/BraveRewardsBalance.java @@ -15,7 +15,6 @@ import org.json.JSONObject; public class BraveRewardsBalance { public static final String WALLET_ANONYMOUS = "anonymous"; - public static final String WALLET_UPHOLD = "uphold"; public static final String WALLET_BLINDED = "blinded"; /** @@ -57,4 +56,4 @@ public class BraveRewardsBalance { "mTotal=" + mTotal + ", mWallets=" + mWallets +'}'; } -} \ No newline at end of file +} diff --git a/android/java/org/chromium/chrome/browser/BraveRewardsNativeWorker.java b/android/java/org/chromium/chrome/browser/BraveRewardsNativeWorker.java index e81a5e3c981..079caa3b1fd 100644 --- a/android/java/org/chromium/chrome/browser/BraveRewardsNativeWorker.java +++ b/android/java/org/chromium/chrome/browser/BraveRewardsNativeWorker.java @@ -191,6 +191,13 @@ public class BraveRewardsNativeWorker { } } + public String getExternalWalletType() { + synchronized (lock) { + return BraveRewardsNativeWorkerJni.get().getExternalWalletType( + mNativeBraveRewardsNativeWorker); + } + } + public double GetWalletRate() { synchronized(lock) { return BraveRewardsNativeWorkerJni.get().getWalletRate(mNativeBraveRewardsNativeWorker); @@ -587,6 +594,15 @@ public class BraveRewardsNativeWorker { } } + @CalledByNative + public void OnGetAdsAccountStatement(boolean success, double next_payment_date, + int ads_received_this_month, double earnings_this_month, double earnings_last_month) { + for (BraveRewardsObserver observer : mObservers) { + observer.OnGetAdsAccountStatement(success, next_payment_date, ads_received_this_month, + earnings_this_month, earnings_last_month); + } + } + @CalledByNative public void OnDisconnectWallet(int error_code, String external_wallet) { for (BraveRewardsObserver observer : mObservers) { @@ -623,6 +639,7 @@ public class BraveRewardsNativeWorker { void init(BraveRewardsNativeWorker caller); void destroy(long nativeBraveRewardsNativeWorker); String getWalletBalance(long nativeBraveRewardsNativeWorker); + String getExternalWalletType(long nativeBraveRewardsNativeWorker); double getWalletRate(long nativeBraveRewardsNativeWorker); void getPublisherInfo(long nativeBraveRewardsNativeWorker, int tabId, String host); String getPublisherURL(long nativeBraveRewardsNativeWorker, int tabId); diff --git a/android/java/org/chromium/chrome/browser/BraveRewardsObserver.java b/android/java/org/chromium/chrome/browser/BraveRewardsObserver.java index ffafa6662f1..cba4b0fd7f8 100644 --- a/android/java/org/chromium/chrome/browser/BraveRewardsObserver.java +++ b/android/java/org/chromium/chrome/browser/BraveRewardsObserver.java @@ -31,4 +31,6 @@ public interface BraveRewardsObserver { default public void OnRefreshPublisher(int status, String publisherKey){}; default public void OnOneTimeTip(){}; default public void OnStartProcess(){}; + default public void OnGetAdsAccountStatement(boolean success, double nextPaymentDate, + int adsReceivedThisMonth, double earningsThisMonth, double earningsLastMonth){}; } diff --git a/android/java/org/chromium/chrome/browser/BraveRewardsPanelPopup.java b/android/java/org/chromium/chrome/browser/BraveRewardsPanelPopup.java index 4898f13d086..a6562751414 100644 --- a/android/java/org/chromium/chrome/browser/BraveRewardsPanelPopup.java +++ b/android/java/org/chromium/chrome/browser/BraveRewardsPanelPopup.java @@ -122,7 +122,6 @@ public class BraveRewardsPanelPopup implements BraveRewardsObserver, BraveReward private static final String REWARDS_NOTIFICATION_NO_INTERNET_ID = "29d835c2-5752-4152-93c3-8a1ded9dd4ec"; private static final int REWARDS_PROMOTION_CLAIM_ERROR = REWARDS_NOTIFICATION_NO_INTERNET + 1; private static final String REWARDS_PROMOTION_CLAIM_ERROR_ID = "rewards_promotion_claim_error_id"; - // // Auto contribute results private static final String AUTO_CONTRIBUTE_SUCCESS = "0"; @@ -1636,7 +1635,6 @@ public class BraveRewardsPanelPopup implements BraveRewardsObserver, BraveReward // mBraveRewardsNativeWorker.GetExternalWallet(); } - /** * OnRecurringDonationUpdated is fired after a publisher was added or removed to/from * recurrent donation list @@ -1703,7 +1701,7 @@ public class BraveRewardsPanelPopup implements BraveRewardsObserver, BraveReward Button btnVerifyWallet = (Button) root.findViewById(R.id.btn_verify_wallet); btnVerifyWallet.setBackgroundResource(R.drawable.wallet_verify_button); if (mExternalWallet != null - && mExternalWallet.getType().equals(BraveUphold.BITFLYER)) { + && mExternalWallet.getType().equals(BraveWalletProvider.BITFLYER)) { btnVerifyWallet.setVisibility(View.INVISIBLE); } } @@ -1833,7 +1831,7 @@ public class BraveRewardsPanelPopup implements BraveRewardsObserver, BraveReward case BraveRewardsExternalWallet.PENDING: case BraveRewardsExternalWallet.VERIFIED: if (walletBalance < WALLET_BALANCE_LIMIT - && mExternalWallet.getType().equals(BraveUphold.UPHOLD) + && mExternalWallet.getType().equals(BraveWalletProvider.UPHOLD) && !isVerifyWalletEnabled()) { showUpholdLoginPopupWindow(btnVerifyWallet); } else { @@ -1848,7 +1846,7 @@ public class BraveRewardsPanelPopup implements BraveRewardsObserver, BraveReward case BraveRewardsExternalWallet.DISCONNECTED_NOT_VERIFIED: case BraveRewardsExternalWallet.DISCONNECTED_VERIFIED: if (walletBalance < WALLET_BALANCE_LIMIT - && mExternalWallet.getType().equals(BraveUphold.UPHOLD) + && mExternalWallet.getType().equals(BraveWalletProvider.UPHOLD) && !isVerifyWalletEnabled()) { showUpholdLoginPopupWindow(btnVerifyWallet); } else { @@ -1910,6 +1908,12 @@ public class BraveRewardsPanelPopup implements BraveRewardsObserver, BraveReward SetVerifyWalletControl(walletStatus); } + @Override + public void OnGetAdsAccountStatement(boolean success, double next_payment_date, + int ads_received_this_month, double earnings_this_month, double earnings_last_month) { + // TODO: Implement + } + /** * Show the "promotion claim failed" error message. * Succesful claims are dismissed by a notification. diff --git a/android/java/org/chromium/chrome/browser/BraveRewardsUserWalletActivity.java b/android/java/org/chromium/chrome/browser/BraveRewardsUserWalletActivity.java index feaaaeb5877..94e201f3e9c 100644 --- a/android/java/org/chromium/chrome/browser/BraveRewardsUserWalletActivity.java +++ b/android/java/org/chromium/chrome/browser/BraveRewardsUserWalletActivity.java @@ -21,16 +21,24 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.BraveRewardsBalance; import org.chromium.chrome.browser.BraveRewardsExternalWallet; import org.chromium.chrome.browser.BraveRewardsNativeWorker; +import org.chromium.chrome.browser.BraveWalletProvider; import org.chromium.chrome.browser.app.BraveActivity; import org.chromium.chrome.browser.init.AsyncInitializationActivity; public class BraveRewardsUserWalletActivity extends AsyncInitializationActivity { public static final String DISCONNECT_WALLET_URL = "chrome://rewards/#disconnect-wallet"; + private String walletType = BraveRewardsNativeWorker.getInstance().getExternalWalletType(); + private String walletTypeString; + @Override protected void triggerLayoutInflation() { setContentView(R.layout.user_wallet_activity); + walletTypeString = walletType.equals(BraveWalletProvider.UPHOLD) + ? getResources().getString(R.string.uphold) + : getResources().getString(R.string.bitflyer); + Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); @@ -50,7 +58,9 @@ public class BraveRewardsUserWalletActivity extends AsyncInitializationActivity TextView txtUserStatus = (TextView) findViewById(R.id.user_status); Button btn1 = (Button) findViewById(R.id.user_wallet_btn1); Button btn2 = null; - Button btnGotoUphold = (Button) findViewById(R.id.user_wallet_go_to_uphold); + Button btnGotoProvider = (Button) findViewById(R.id.user_wallet_go_to_provider); + btnGotoProvider.setText(String.format( + getResources().getString(R.string.user_wallet_goto_provider), walletTypeString)); if (status < BraveRewardsExternalWallet.NOT_CONNECTED || status > BraveRewardsExternalWallet.PENDING) { @@ -64,7 +74,7 @@ public class BraveRewardsUserWalletActivity extends AsyncInitializationActivity // Buttons: // Add funds // Withdraw - // Go to uphold + // Go to provider // Disconnect btn1.setText(getResources().getString(R.string.brave_rewards_local_panel_add_funds)); btn2.setText(getResources().getString(R.string.user_wallet_withdraw_funds)); @@ -78,7 +88,7 @@ public class BraveRewardsUserWalletActivity extends AsyncInitializationActivity // CONNECTED or PENDING // Buttons: // Complete verification - // Go to uphold + // Go to provider // Disconnect btn1.setText(getResources().getString(R.string.user_wallet_complete_verification)); SetBtnOpenUrlClickHandler( @@ -86,7 +96,7 @@ public class BraveRewardsUserWalletActivity extends AsyncInitializationActivity } SetBtnOpenUrlClickHandler( - btnGotoUphold, intent.getStringExtra(BraveRewardsExternalWallet.ACCOUNT_URL)); + btnGotoProvider, intent.getStringExtra(BraveRewardsExternalWallet.ACCOUNT_URL)); String userId = intent.getStringExtra(BraveRewardsExternalWallet.USER_NAME); txtUserId.setText(userId); diff --git a/android/java/org/chromium/chrome/browser/BraveRewardsVerifyWalletActivity.java b/android/java/org/chromium/chrome/browser/BraveRewardsVerifyWalletActivity.java index 00da466b4f2..aeee13b0922 100644 --- a/android/java/org/chromium/chrome/browser/BraveRewardsVerifyWalletActivity.java +++ b/android/java/org/chromium/chrome/browser/BraveRewardsVerifyWalletActivity.java @@ -19,21 +19,55 @@ import android.widget.TextView; import org.chromium.chrome.R; import org.chromium.chrome.browser.BraveRewardsExternalWallet; import org.chromium.chrome.browser.BraveRewardsHelper; -import org.chromium.chrome.browser.BraveUphold; +import org.chromium.chrome.browser.BraveRewardsNativeWorker; +import org.chromium.chrome.browser.BraveWalletProvider; import org.chromium.chrome.browser.app.BraveActivity; import java.util.Locale; public class BraveRewardsVerifyWalletActivity extends Activity { + private String walletType = BraveRewardsNativeWorker.getInstance().getExternalWalletType(); + private String walletTypeString; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.verify_wallet_activity); + + walletTypeString = walletType.equals(BraveWalletProvider.UPHOLD) + ? getResources().getString(R.string.uphold) + : getResources().getString(R.string.bitflyer); + + setTextForWalletTypes(); SetVerifyWalletBtnClickHandler(); SetUpholdLinkHandler(); } + void setTextForWalletTypes() { + TextView verifyWalletBenefitText1 = (TextView) findViewById(R.id.verify_wallet_benefit_1); + verifyWalletBenefitText1.setText(walletType.equals(BraveWalletProvider.UPHOLD) + ? getResources().getString(R.string.verify_wallet_uphold_benefits1) + : getResources().getString(R.string.verify_wallet_bitflyer_benefits1)); + TextView verifyWalletBenefitText2 = (TextView) findViewById(R.id.verify_wallet_benefit_2); + verifyWalletBenefitText2.setText(walletType.equals(BraveWalletProvider.UPHOLD) + ? getResources().getString(R.string.verify_wallet_uphold_benefits2) + : getResources().getString(R.string.verify_wallet_bitflyer_benefits2)); + TextView verifyWalletBenefitText3 = (TextView) findViewById(R.id.verify_wallet_benefit_3); + verifyWalletBenefitText3.setText(walletType.equals(BraveWalletProvider.UPHOLD) + ? getResources().getString(R.string.verify_wallet_uphold_benefits3) + : getResources().getString(R.string.verify_wallet_bitflyer_benefits3)); + + TextView verifyWalletProviderNoteText = + (TextView) findViewById(R.id.verify_wallet_provider_note_txt); + verifyWalletProviderNoteText.setText(String.format( + getResources().getString(R.string.verify_wallet_provider_note1), walletTypeString)); + + TextView verifyWalletBraveNoteText = + (TextView) findViewById(R.id.verify_wallet_brave_note_txt); + verifyWalletBraveNoteText.setText(String.format( + getResources().getString(R.string.verify_wallet_brave_note1), walletTypeString)); + } + void SetVerifyWalletBtnClickHandler() { Button btnVerifyWallet = (Button)findViewById(R.id.verify_wallet_btn); btnVerifyWallet.setOnClickListener( (View v) -> { @@ -49,7 +83,7 @@ public class BraveRewardsVerifyWalletActivity extends Activity { void SetUpholdLinkHandler() { TextView uphold_link = (TextView)findViewById(R.id.service_provider_txt); final String part1 = getResources().getString(R.string.verify_wallet_service_note); - final String part2 = getResources().getString(R.string.verify_wallet_uphold); + final String part2 = walletTypeString; final String built_service_str = String.format(Locale.US, "%s %s", part1, part2); Spanned toInsert = BraveRewardsHelper.spannedFromHtmlString(built_service_str); uphold_link.setText(toInsert); @@ -63,7 +97,8 @@ public class BraveRewardsVerifyWalletActivity extends Activity { if (BraveRewardsHelper.subtextAtOffset(built_service_str, part2, offset) ){ Intent intent = new Intent(); - intent.putExtra(BraveActivity.OPEN_URL, BraveUphold.UPHOLD_ORIGIN_URL); + intent.putExtra( + BraveActivity.OPEN_URL, BraveWalletProvider.UPHOLD_ORIGIN_URL); setResult(RESULT_OK, intent); finish(); event_consumed = true; diff --git a/android/java/org/chromium/chrome/browser/BraveUphold.java b/android/java/org/chromium/chrome/browser/BraveUphold.java deleted file mode 100644 index 2c4fce88312..00000000000 --- a/android/java/org/chromium/chrome/browser/BraveUphold.java +++ /dev/null @@ -1,153 +0,0 @@ -/** Copyright (c) 2020 The Brave Authors. All rights reserved. - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ -package org.chromium.chrome.browser; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.net.Uri; -import android.text.TextUtils; - -import org.json.JSONException; -import org.json.JSONObject; - -import org.chromium.base.ContextUtils; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.BraveRewardsBalance; -import org.chromium.chrome.browser.BraveRewardsHelper; -import org.chromium.chrome.browser.BraveRewardsNativeWorker; -import org.chromium.chrome.browser.BraveRewardsObserver; -import org.chromium.chrome.browser.app.BraveActivity; -import org.chromium.chrome.browser.externalnav.BraveExternalNavigationHandler; -import org.chromium.components.external_intents.ExternalNavigationParams; - -import java.util.Locale; - -//used from org.chromium.chrome.browser.externalnav -public class BraveUphold implements BraveRewardsObserver { - public static final String UPHOLD_REDIRECT_URL = "rewards://uphold"; - public static final String UPHOLD_REDIRECT_URL_KEY = "redirect_url"; - public static final String ACTION_VALUE = "authorization"; - public static final String UPHOLD_SUPPORT_URL = "http://uphold.com/en/brave/support"; - public static final String UPHOLD_ORIGIN_URL = "http://uphold.com"; - - // Wallet types - public static final String UPHOLD = "uphold"; - public static final String BITFLYER = "bitflyer"; - - private static int UNKNOWN_ERROR_CODE = -1; - - private ExternalNavigationParams mExternalNavigationParams; - private BraveExternalNavigationHandler mBraveExternalNavigationHandler; - private BraveRewardsNativeWorker rewardsNativeProxy; - - public void CompleteUpholdVerification(ExternalNavigationParams params, - BraveExternalNavigationHandler handler) { - mExternalNavigationParams = params; - mBraveExternalNavigationHandler = handler; - rewardsNativeProxy = BraveRewardsNativeWorker.getInstance(); - - Uri uri = Uri.parse(params.getUrl().getSpec()); - rewardsNativeProxy.AddObserver(this); - String path = uri.getPath(); - String query = uri.getQuery(); - - if (TextUtils.isEmpty(path) || TextUtils.isEmpty(query)) { - rewardsNativeProxy.RemoveObserver(this); - ReleaseDependencies(); - ShowErrorMessageBox(UNKNOWN_ERROR_CODE); - return; - } - - // Ledger expects: - // path: "/uphold/path" - // query: "?query" - path = String.format(Locale.US,"/%s/%s", - BraveRewardsBalance.WALLET_UPHOLD, path); - query = String.format(Locale.US,"?%s", query); - rewardsNativeProxy.ProcessRewardsPageUrl(path, query); - } - - @Override - public void OnProcessRewardsPageUrl(int error_code, - String wallet_type, String action, - String json_args ) { - - //remove observer - if (rewardsNativeProxy != null) { - rewardsNativeProxy.RemoveObserver(this); - } - - String redirect_url = parseJsonArgs (json_args); - if (BraveRewardsNativeWorker.LEDGER_OK == error_code && - TextUtils.equals(action, ACTION_VALUE)) { - - //wallet is verified: redirect to chrome://rewards for now - if (TextUtils.isEmpty(redirect_url)) { - redirect_url = BraveActivity.REWARDS_SETTINGS_URL; - } - mBraveExternalNavigationHandler. - clobberCurrentTabWithFallbackUrl (redirect_url, - mExternalNavigationParams); - - // temporary: open Rewards Panel to show wallet transition state. - // remove this step once settings activity has this info - BraveActivity.getBraveActivity().openRewardsPanel(); - ReleaseDependencies(); - } - else { - ShowErrorMessageBox(error_code); - } - } - - private String parseJsonArgs(String json_args) { - String redirect_url = ""; - try { - JSONObject jsonObj = new JSONObject(json_args); - if (jsonObj.has(UPHOLD_REDIRECT_URL_KEY)) { - redirect_url = jsonObj.getString(UPHOLD_REDIRECT_URL_KEY); - } - } - catch(JSONException e){ } - return redirect_url; - } - - private void ReleaseDependencies() { - mExternalNavigationParams = null; - mBraveExternalNavigationHandler = null; - } - - private void ShowErrorMessageBox (int error_code) { - String msg = ""; - String msg_title = ""; - Context context = ContextUtils.getApplicationContext(); - AlertDialog.Builder builder = new AlertDialog.Builder( - BraveRewardsHelper.getChromeTabbedActivity(), - R.style.Theme_Chromium_AlertDialog); - - if (BraveRewardsNativeWorker.BAT_NOT_ALLOWED == error_code) { - msg = context.getResources().getString(R.string.bat_not_allowed_in_region); - msg_title = context.getResources().getString(R.string.bat_not_allowed_in_region_title); - } - else { - msg = context.getResources().getString(R.string.wallet_verification_generic_error); - msg_title = context.getResources().getString(R.string.wallet_verification_generic_error_title); - } - builder.setMessage(msg) - .setTitle (msg_title) - .setPositiveButton(R.string.ok, (DialogInterface dialog, int which)-> { - mBraveExternalNavigationHandler. - clobberCurrentTabWithFallbackUrl (UPHOLD_SUPPORT_URL, - mExternalNavigationParams); - }) - .setOnDismissListener((DialogInterface dialog)-> { - ReleaseDependencies(); - }); - - AlertDialog dlg = builder.create(); - dlg.show(); - } -} \ No newline at end of file diff --git a/android/java/org/chromium/chrome/browser/BraveWalletProvider.java b/android/java/org/chromium/chrome/browser/BraveWalletProvider.java new file mode 100644 index 00000000000..a53d414a80a --- /dev/null +++ b/android/java/org/chromium/chrome/browser/BraveWalletProvider.java @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2020 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.chromium.chrome.browser; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.net.Uri; +import android.text.TextUtils; + +import org.json.JSONException; +import org.json.JSONObject; + +import org.chromium.base.ContextUtils; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.BraveRewardsBalance; +import org.chromium.chrome.browser.BraveRewardsHelper; +import org.chromium.chrome.browser.BraveRewardsNativeWorker; +import org.chromium.chrome.browser.BraveRewardsObserver; +import org.chromium.chrome.browser.app.BraveActivity; +import org.chromium.chrome.browser.externalnav.BraveExternalNavigationHandler; +import org.chromium.components.external_intents.ExternalNavigationParams; + +import java.util.Locale; + +// Used from org.chromium.chrome.browser.externalnav +public class BraveWalletProvider implements BraveRewardsObserver { + public static final String ACTION_VALUE = "authorization"; + + public static final String REDIRECT_URL_KEY = "redirect_url"; + + public static final String UPHOLD_REDIRECT_URL = "rewards://uphold"; + public static final String UPHOLD_SUPPORT_URL = "http://uphold.com/en/brave/support"; + public static final String UPHOLD_ORIGIN_URL = "http://uphold.com"; + + public static final String BITFLYER_REDIRECT_URL = "rewards://bitflyer"; + + // Wallet types + public static final String UPHOLD = "uphold"; + public static final String BITFLYER = "bitflyer"; + + private static int UNKNOWN_ERROR_CODE = -1; + + private ExternalNavigationParams mExternalNavigationParams; + private BraveExternalNavigationHandler mBraveExternalNavigationHandler; + private BraveRewardsNativeWorker rewardsNativeProxy; + + public void completeWalletProviderVerification( + ExternalNavigationParams params, BraveExternalNavigationHandler handler) { + mExternalNavigationParams = params; + mBraveExternalNavigationHandler = handler; + rewardsNativeProxy = BraveRewardsNativeWorker.getInstance(); + + Uri uri = Uri.parse(params.getUrl().getSpec()); + rewardsNativeProxy.AddObserver(this); + String path = uri.getPath(); + String query = uri.getQuery(); + + if (TextUtils.isEmpty(path) || TextUtils.isEmpty(query)) { + rewardsNativeProxy.RemoveObserver(this); + releaseDependencies(); + showErrorMessageBox(UNKNOWN_ERROR_CODE); + return; + } + + // Ledger expects: + // path: "/provider/path" + // query: "?query" + path = String.format(Locale.US, "/%s/%s", rewardsNativeProxy.getExternalWalletType(), path); + query = String.format(Locale.US, "?%s", query); + rewardsNativeProxy.ProcessRewardsPageUrl(path, query); + } + + @Override + public void OnProcessRewardsPageUrl( + int errorCode, String walletType, String action, String jsonArgs) { + // remove observer + if (rewardsNativeProxy != null) { + rewardsNativeProxy.RemoveObserver(this); + } + + String redirectUrl = parseJsonArgs(jsonArgs); + if (BraveRewardsNativeWorker.LEDGER_OK == errorCode + && TextUtils.equals(action, ACTION_VALUE)) { + // wallet is verified: redirect to chrome://rewards for now + if (TextUtils.isEmpty(redirectUrl)) { + redirectUrl = BraveActivity.REWARDS_SETTINGS_URL; + } + mBraveExternalNavigationHandler.clobberCurrentTabWithFallbackUrl( + redirectUrl, mExternalNavigationParams); + + // temporary: open Rewards Panel to show wallet transition state. + // remove this step once settings activity has this info + BraveActivity.getBraveActivity().openRewardsPanel(); + releaseDependencies(); + } else { + showErrorMessageBox(errorCode); + } + } + + private String parseJsonArgs(String jsonArgs) { + String redirect_url = ""; + try { + JSONObject jsonObj = new JSONObject(jsonArgs); + if (jsonObj.has(REDIRECT_URL_KEY)) { + redirect_url = jsonObj.getString(REDIRECT_URL_KEY); + } + } catch (JSONException e) { + } + return redirect_url; + } + + private void releaseDependencies() { + mExternalNavigationParams = null; + mBraveExternalNavigationHandler = null; + } + + private void showErrorMessageBox(int errorCode) { + String message = ""; + String messageTitle = ""; + Context context = ContextUtils.getApplicationContext(); + AlertDialog.Builder builder = new AlertDialog.Builder( + BraveRewardsHelper.getChromeTabbedActivity(), R.style.Theme_Chromium_AlertDialog); + + if (BraveRewardsNativeWorker.BAT_NOT_ALLOWED == errorCode) { + message = context.getResources().getString(R.string.bat_not_allowed_in_region); + messageTitle = + context.getResources().getString(R.string.bat_not_allowed_in_region_title); + } else { + message = context.getResources().getString(R.string.wallet_verification_generic_error); + messageTitle = context.getResources().getString( + R.string.wallet_verification_generic_error_title); + } + builder.setMessage(message) + .setTitle(messageTitle) + .setPositiveButton(R.string.ok, + (DialogInterface dialog, int which) -> { + mBraveExternalNavigationHandler.clobberCurrentTabWithFallbackUrl( + UPHOLD_SUPPORT_URL, mExternalNavigationParams); + }) + .setOnDismissListener((DialogInterface dialog) -> { releaseDependencies(); }); + + AlertDialog dialog = builder.create(); + dialog.show(); + } +} diff --git a/android/java/org/chromium/chrome/browser/externalnav/BraveExternalNavigationHandler.java b/android/java/org/chromium/chrome/browser/externalnav/BraveExternalNavigationHandler.java index 59217d4e515..69b0be717d4 100644 --- a/android/java/org/chromium/chrome/browser/externalnav/BraveExternalNavigationHandler.java +++ b/android/java/org/chromium/chrome/browser/externalnav/BraveExternalNavigationHandler.java @@ -7,7 +7,7 @@ package org.chromium.chrome.browser.externalnav; import android.annotation.SuppressLint; -import org.chromium.chrome.browser.BraveUphold; +import org.chromium.chrome.browser.BraveWalletProvider; import org.chromium.components.external_intents.ExternalNavigationDelegate; import org.chromium.components.external_intents.ExternalNavigationHandler; import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult; @@ -15,7 +15,7 @@ import org.chromium.components.external_intents.ExternalNavigationParams; import org.chromium.url.GURL; public class BraveExternalNavigationHandler extends ExternalNavigationHandler { - private BraveUphold mBraveUphold; + private BraveWalletProvider mBraveWalletProvider; public BraveExternalNavigationHandler(ExternalNavigationDelegate delegate) { super(delegate); @@ -23,21 +23,28 @@ public class BraveExternalNavigationHandler extends ExternalNavigationHandler { @Override public OverrideUrlLoadingResult shouldOverrideUrlLoading(ExternalNavigationParams params) { - if (isUpholdOverride(params)) { - CompleteUpholdVerification(params); + if (isWalletProviderOverride(params)) { + completeWalletProviderVerification(params); return OverrideUrlLoadingResult.forClobberingTab(); } return super.shouldOverrideUrlLoading(params); } - private boolean isUpholdOverride(ExternalNavigationParams params) { - if (!params.getUrl().getSpec().startsWith(BraveUphold.UPHOLD_REDIRECT_URL)) return false; - return true; + private boolean isWalletProviderOverride(ExternalNavigationParams params) { + if (params.getUrl().getSpec().startsWith(BraveWalletProvider.UPHOLD_REDIRECT_URL)) { + return true; + } + + if (params.getUrl().getSpec().startsWith(BraveWalletProvider.BITFLYER_REDIRECT_URL)) { + return true; + } + + return false; } - private void CompleteUpholdVerification(ExternalNavigationParams params) { - mBraveUphold = new BraveUphold(); - mBraveUphold.CompleteUpholdVerification(params, this); + private void completeWalletProviderVerification(ExternalNavigationParams params) { + mBraveWalletProvider = new BraveWalletProvider(); + mBraveWalletProvider.completeWalletProviderVerification(params, this); } @SuppressLint("VisibleForTests") @@ -56,4 +63,4 @@ public class BraveExternalNavigationHandler extends ExternalNavigationHandler { GURL browserFallbackGURL = new GURL(browserFallbackUrl); return clobberCurrentTab(browserFallbackGURL, params.getReferrerUrl()); } -} \ No newline at end of file +} diff --git a/android/java/res/layout-land/verify_wallet_activity.xml b/android/java/res/layout-land/verify_wallet_activity.xml index ed1be17bb15..fb3d7e36523 100644 --- a/android/java/res/layout-land/verify_wallet_activity.xml +++ b/android/java/res/layout-land/verify_wallet_activity.xml @@ -78,9 +78,9 @@ android:textAlignment="center"/> - \ No newline at end of file + diff --git a/android/java/res/layout/verify_wallet_activity.xml b/android/java/res/layout/verify_wallet_activity.xml index f95bd920db9..6578767b13f 100644 --- a/android/java/res/layout/verify_wallet_activity.xml +++ b/android/java/res/layout/verify_wallet_activity.xml @@ -48,6 +48,7 @@ android:textStyle="bold" /> @@ -118,21 +118,21 @@ android:textSize="@dimen/verify_wallet_header4_font_size"/> diff --git a/browser/brave_rewards/android/brave_rewards_native_worker.cc b/browser/brave_rewards/android/brave_rewards_native_worker.cc index f3823bce804..d3ec2bbc877 100644 --- a/browser/brave_rewards/android/brave_rewards_native_worker.cc +++ b/browser/brave_rewards/android/brave_rewards_native_worker.cc @@ -251,6 +251,40 @@ BraveRewardsNativeWorker::GetWalletBalance(JNIEnv* env) { return base::android::ConvertUTF8ToJavaString(env, json_balance); } +base::android::ScopedJavaLocalRef +BraveRewardsNativeWorker::GetExternalWalletType(JNIEnv* env) { + std::string wallet_type; + if (brave_rewards_service_) { + wallet_type = brave_rewards_service_->GetExternalWalletType(); + } + + return base::android::ConvertUTF8ToJavaString(env, wallet_type); +} + +void BraveRewardsNativeWorker::GetAdsAccountStatement(JNIEnv* env) { + auto* ads_service = brave_ads::AdsServiceFactory::GetForProfile( + ProfileManager::GetActiveUserProfile()->GetOriginalProfile()); + if (!ads_service) { + return; + } + ads_service->GetAccountStatement( + base::BindOnce(&BraveRewardsNativeWorker::OnGetAdsAccountStatement, + weak_factory_.GetWeakPtr())); +} + +void BraveRewardsNativeWorker::OnGetAdsAccountStatement( + bool success, + double next_payment_date, + int ads_received_this_month, + double earnings_this_month, + double earnings_last_month) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_BraveRewardsNativeWorker_OnGetAdsAccountStatement( + env, weak_java_brave_rewards_native_worker_.get(env), success, + next_payment_date * 1000, ads_received_this_month, earnings_this_month, + earnings_last_month); +} + double BraveRewardsNativeWorker::GetWalletRate(JNIEnv* env) { return parameters_.rate; } diff --git a/browser/brave_rewards/android/brave_rewards_native_worker.h b/browser/brave_rewards/android/brave_rewards_native_worker.h index b8539d509fb..ec96406b970 100644 --- a/browser/brave_rewards/android/brave_rewards_native_worker.h +++ b/browser/brave_rewards/android/brave_rewards_native_worker.h @@ -47,6 +47,11 @@ class BraveRewardsNativeWorker : public brave_rewards::RewardsServiceObserver, base::android::ScopedJavaLocalRef GetWalletBalance(JNIEnv* env); + base::android::ScopedJavaLocalRef GetExternalWalletType( + JNIEnv* env); + + void GetAdsAccountStatement(JNIEnv* env); + double GetWalletRate(JNIEnv* env); base::android::ScopedJavaLocalRef GetPublisherURL(JNIEnv* env, @@ -223,6 +228,12 @@ class BraveRewardsNativeWorker : public brave_rewards::RewardsServiceObserver, void OnStartProcess(); + void OnGetAdsAccountStatement(bool success, + double next_payment_date, + int ads_received_this_month, + double earnings_this_month, + double earnings_last_month); + JavaObjectWeakGlobalRef weak_java_brave_rewards_native_worker_; brave_rewards::RewardsService* brave_rewards_service_; ledger::type::RewardsParameters parameters_; diff --git a/browser/ui/android/strings/android_brave_strings.grd b/browser/ui/android/strings/android_brave_strings.grd index 1375f0bb21f..683a09e02d6 100644 --- a/browser/ui/android/strings/android_brave_strings.grd +++ b/browser/ui/android/strings/android_brave_strings.grd @@ -969,29 +969,41 @@ Are you sure you want to do this? But if you verify, you can... - + Withdraw BAT that you earn from viewing privacy-respecting ads - + Purchase additional BAT with credit cards and other sources - + Withdraw BAT that you may have previously added to your Brave Rewards wallet + + Withdraw BAT that you earn from viewing privacy-respecting ads + + + Purchase additional BAT with credit cards and other sources + + + Withdraw BAT that you may have previously added to your Brave Rewards wallet + Verify Wallet Our wallet service is provided by - + Uphold - + + Bitflyer + + Uphold may require you to verify your identity based on services requested. - Brave Software Inc. does not process, store, or access any of the personal information that you provide to Uphold when you establish an account with them. + Brave Software Inc. does not process, store, or access any of the personal information that you provide to %1$s when you establish an account with them. Complete wallet verification @@ -999,8 +1011,8 @@ Are you sure you want to do this? User Wallet - - Go to your Uphold account + + Go to my %1$s account Disconnect from Brave Rewards diff --git a/components/brave_rewards/browser/rewards_service.h b/components/brave_rewards/browser/rewards_service.h index 3c9d00af8cf..42434be17ed 100644 --- a/components/brave_rewards/browser/rewards_service.h +++ b/components/brave_rewards/browser/rewards_service.h @@ -312,6 +312,8 @@ class RewardsService : public KeyedService { virtual void GetExternalWallet(GetExternalWalletCallback callback) = 0; + virtual std::string GetExternalWalletType() const = 0; + virtual const std::vector GetExternalWalletProviders() const = 0; virtual void ProcessRewardsPageUrl( diff --git a/components/brave_rewards/browser/rewards_service_impl.cc b/components/brave_rewards/browser/rewards_service_impl.cc index 5ad23e3116f..4872edfd449 100644 --- a/components/brave_rewards/browser/rewards_service_impl.cc +++ b/components/brave_rewards/browser/rewards_service_impl.cc @@ -1246,6 +1246,7 @@ void RewardsServiceImpl::OnAttestationAndroid( if (!token_received) { std::move(callback).Run(ledger::type::Result::LEDGER_ERROR, nullptr); + return; } base::Value solution(base::Value::Type::DICTIONARY); diff --git a/components/brave_rewards/browser/rewards_service_impl.h b/components/brave_rewards/browser/rewards_service_impl.h index 342deccd50f..3af5a025ceb 100644 --- a/components/brave_rewards/browser/rewards_service_impl.h +++ b/components/brave_rewards/browser/rewards_service_impl.h @@ -296,7 +296,7 @@ class RewardsServiceImpl : public RewardsService, void GetExternalWallet(GetExternalWalletCallback callback) override; - std::string GetExternalWalletType() const; + std::string GetExternalWalletType() const override; const std::vector GetExternalWalletProviders() const override; diff --git a/components/brave_rewards/resources/android_page/actions/rewards_actions.ts b/components/brave_rewards/resources/android_page/actions/rewards_actions.ts index 78cca864515..d0c8d095fba 100644 --- a/components/brave_rewards/resources/android_page/actions/rewards_actions.ts +++ b/components/brave_rewards/resources/android_page/actions/rewards_actions.ts @@ -9,24 +9,14 @@ import { types } from '../constants/rewards_types' export const isInitialized = () => action(types.IS_INITIALIZED) -export const onSettingSave = (key: string, value: any) => action(types.ON_SETTING_SAVE, { +export const onSettingSave = (key: string, value: any, persist: boolean = true) => action(types.ON_SETTING_SAVE, { key, - value + value, + persist }) export const getRewardsParameters = () => action(types.GET_REWARDS_PARAMETERS) -export const disconnectWallet = () => action(types.DISCONNECT_WALLET) - -export const disconnectWalletError = () => action(types.DISCONNECT_WALLET_ERROR) - -export const getExternalWallet = () => action(types.GET_EXTERNAL_WALLET) - -export const onExternalWallet = (result: number, wallet: Rewards.ExternalWallet) => action(types.ON_EXTERNAL_WALLET, { - result, - wallet -}) - export const onRewardsParameters = (properties: Rewards.RewardsParameters) => action(types.ON_REWARDS_PARAMETERS, { properties @@ -48,14 +38,36 @@ export const claimPromotion = (promotionId: string) => action(types.CLAIM_PROMOT promotionId }) +export const onClaimPromotion = (properties: Rewards.Captcha) => action(types.ON_CLAIM_PROMOTION, { + properties +}) + +export const attestPromotion = (promotionId: string, x: number, y: number) => action(types.ATTEST_PROMOTION, { + promotionId, + x, + y +}) + export const onPromotionFinish = (properties: Rewards.PromotionFinish) => action(types.ON_PROMOTION_FINISH, { properties }) +export const resetPromotion = (promotionId: string) => action(types.RESET_PROMOTION, { + promotionId +}) + export const deletePromotion = (promotionId: string) => action(types.DELETE_PROMOTION, { promotionId }) +export const recoverWallet = (key: string) => action(types.RECOVER_WALLET, { + key +}) + +export const onRecoverWalletData = (result: number) => action(types.ON_RECOVER_WALLET_DATA, { + result +}) + export const onModalBackupClose = () => action(types.ON_MODAL_BACKUP_CLOSE) export const onModalBackupOpen = () => action(types.ON_MODAL_BACKUP_OPEN) @@ -82,6 +94,10 @@ export const onBalanceReport = (properties: {month: number, year: number, report report: properties.report }) +export const onExternalWalletProviderList = (list: Rewards.ExternalWalletProvider[]) => action(types.ON_EXTERNAL_WALLET_PROVIDER_LIST, { + list +}) + export const getBalanceReport = (month: number, year: number) => action(types.GET_BALANCE_REPORT, { month, year @@ -121,6 +137,70 @@ export const onAdsData = (adsData: Rewards.AdsData) => action(types.ON_ADS_DATA, adsData }) +export const getAdsHistory = () => action(types.GET_ADS_HISTORY) + +export const onAdsHistory = (adsHistory: Rewards.AdsHistory[]) => action(types.ON_ADS_HISTORY, { + adsHistory +}) + +export const toggleAdThumbUp = (uuid: string, creativeSetId: string, likeAction: number) => action(types.TOGGLE_AD_THUMB_UP, { + uuid, + creativeSetId, + likeAction +}) + +export const onToggleAdThumbUp = (result: Rewards.ToggleLikeAction) => action(types.ON_TOGGLE_AD_THUMB_UP, { + result +}) + +export const toggleAdThumbDown = (uuid: string, creativeSetId: string, likeAction: number) => action(types.TOGGLE_AD_THUMB_DOWN, { + uuid, + creativeSetId, + likeAction +}) + +export const onToggleAdThumbDown = (result: Rewards.ToggleLikeAction) => action(types.ON_TOGGLE_AD_THUMB_DOWN, { + result +}) + +export const toggleAdOptIn = (category: string, optAction: number) => action(types.TOGGLE_AD_OPT_IN, { + category, + optAction +}) + +export const onToggleAdOptIn = (result: Rewards.ToggleOptAction) => action(types.ON_TOGGLE_AD_OPT_IN, { + result +}) + +export const toggleAdOptOut = (category: string, optAction: number) => action(types.TOGGLE_AD_OPT_OUT, { + category, + optAction +}) + +export const onToggleAdOptOut = (result: Rewards.ToggleOptAction) => action(types.ON_TOGGLE_AD_OPT_OUT, { + result +}) + +export const toggleSavedAd = (uuid: string, creativeSetId: string, savedAd: boolean) => action(types.TOGGLE_SAVED_AD, { + uuid, + creativeSetId, + savedAd +}) + +export const onToggleSavedAd = (result: Rewards.ToggleSavedAd) => action(types.ON_TOGGLE_SAVED_AD, { + result +}) + +export const toggleFlaggedAd = (uuid: string, creativeSetId: string, flaggedAd: boolean) => action(types.TOGGLE_FLAGGED_AD, { + uuid, + creativeSetId, + flaggedAd +}) + +export const onToggleFlaggedAd = (result: Rewards.ToggleFlaggedAd) => action(types.ON_TOGGLE_FLAGGED_AD, { + result +}) + export const onAdsSettingSave = (key: string, value: any) => action(types.ON_ADS_SETTING_SAVE, { key, value @@ -174,10 +254,96 @@ export const onBalance = (status: number, balance: Rewards.Balance) => action(ty balance }) +export const getExternalWallet = () => action(types.GET_EXTERNAL_WALLET) + +export const onExternalWallet = (result: number, wallet: Rewards.ExternalWallet) => action(types.ON_EXTERNAL_WALLET, { + result, + wallet +}) + +export const processRewardsPageUrl = (path: string, query: string) => action(types.PROCESS_REWARDS_PAGE_URL, { + path, + query +}) + +export const onProcessRewardsPageUrl = (data: Rewards.ProcessRewardsPageUrl) => action(types.ON_PROCESS_REWARDS_PAGE_URL, { + data +}) + +export const hideRedirectModal = () => action(types.HIDE_REDIRECT_MODAL) + +export const disconnectWallet = () => action(types.DISCONNECT_WALLET) + +export const getMonthlyReport = (month?: number, year?: number) => action(types.GET_MONTHLY_REPORT, { + month, + year +}) + +export const onMonthlyReport = (properties: { result: number, month: number, year: number, report: Rewards.MonthlyReport}) => action(types.ON_MONTHLY_REPORT, { + result: properties.result, + month: properties.month, + year: properties.year, + report: properties.report +}) + +export const onReconcileStampReset = () => action(types.ON_RECONCILE_STAMP_RESET) + +export const getMonthlyReportIds = () => action(types.GET_MONTHLY_REPORT_IDS) + +export const onMonthlyReportIds = (ids: string[]) => action(types.ON_MONTHLY_REPORT_IDS, ids) + +export const dismissPromoPrompt = (promo: string) => action(types.DISMISS_PROMO_PROMPT, { + promo +}) + +export const getCountryCode = () => action(types.GET_COUNTRY_CODE) + +export const onCountryCode = (countryCode: string) => action(types.ON_COUNTRY_CODE, { + countryCode +}) + export const onInitialized = (result: boolean) => action(types.ON_INITIALIZED, { result }) +export const completeReset = () => action(types.COMPLETE_RESET) + +export const onCompleteReset = (success: boolean) => action(types.ON_COMPLETE_RESET, { + success +}) + +export const getPaymentId = () => action(types.GET_PAYMENT_ID) + +export const disconnectWalletError = () => action(types.DISCONNECT_WALLET_ERROR) + +export const onPaymentId = (paymentId: string) => action(types.ON_PAYMENT_ID, { + paymentId +}) + +export const getWalletPassphrase = () => action(types.GET_WALLET_PASSPHRASE) + +export const onWalletPassphrase = (passphrase: string) => action(types.ON_WALLET_PASSPHRASE, { + passphrase +}) + +export const getOnboardingStatus = () => action(types.GET_ONBOARDING_STATUS) + +export const onOnboardingStatus = (showOnboarding: boolean) => action(types.ON_ONBOARDING_STATUS, { + showOnboarding +}) + +export const saveOnboardingResult = (result: 'opted-in' | 'dismissed') => action(types.SAVE_ONBOARDING_RESULT, { + result +}) + +export const getEnabledInlineTippingPlatforms = () => action(types.GET_ENABLED_INLINE_TIPPING_PLATFORMS) + +export const onEnabledInlineTippingPlatforms = (platforms: string[]) => action(types.ON_ENABLED_INLINE_TIPPING_PLATFORMS, { + platforms +}) + +export const restartBrowser = () => action(types.RESTART_BROWSER) + export const onPrefChanged = (key: string) => action(types.ON_PREF_CHANGED, { key }) diff --git a/components/brave_rewards/resources/android_page/assets/connect_wallet.svg b/components/brave_rewards/resources/android_page/assets/connect_wallet.svg new file mode 100644 index 00000000000..013de1fd2e6 --- /dev/null +++ b/components/brave_rewards/resources/android_page/assets/connect_wallet.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/brave_rewards/resources/android_page/assets/green_check.svg b/components/brave_rewards/resources/android_page/assets/green_check.svg new file mode 100644 index 00000000000..f59dee7c128 --- /dev/null +++ b/components/brave_rewards/resources/android_page/assets/green_check.svg @@ -0,0 +1,3 @@ + + + diff --git a/components/brave_rewards/resources/android_page/brave_rewards_page.tsx b/components/brave_rewards/resources/android_page/brave_rewards_page.tsx index 6a046e9b0b9..17239fc4821 100644 --- a/components/brave_rewards/resources/android_page/brave_rewards_page.tsx +++ b/components/brave_rewards/resources/android_page/brave_rewards_page.tsx @@ -9,30 +9,37 @@ import { initLocale } from 'brave-ui' import { bindActionCreators } from 'redux' require('emptykit.css') +import { LocaleContext } from '../shared/lib/locale_context' +import { WithThemeVariables } from '../shared/components/with_theme_variables' + // Components import App from './components/app' require('../../../../ui/webui/resources/fonts/muli.css') require('../../../../ui/webui/resources/fonts/poppins.css') -import { WithThemeVariables } from '../shared/components/with_theme_variables' - // Utils import { ThemeProvider } from 'styled-components' import { loadTimeData } from '../../../common/loadTimeData' import store from './store' import Theme from 'brave-ui/theme/brave-default' -import { getActions as getUtilActions, getCurrentBalanceReport, setActions } from './utils' +import { getActions as getUtilActions, setActions, getCurrentBalanceReport } from './utils' import * as rewardsActions from './actions/rewards_actions' function initialize () { initLocale(loadTimeData.data_) + const localeContext = { + getString: (key: string) => loadTimeData.getString(key) + } + render( - - - + + + + + , document.getElementById('root')) @@ -50,12 +57,23 @@ function getActions () { function rewardsParameters (properties: Rewards.RewardsParameters) { getActions().onRewardsParameters(properties) + // Get the current AC amount after rewards parameters have been + // updated, as the default AC amount may have been changed. + getActions().getContributionAmount() } function promotions (properties: Rewards.PromotionResponse) { getActions().onPromotions(properties) } +function claimPromotion (properties: Rewards.Captcha) { + getActions().onClaimPromotion(properties) +} + +function recoverWalletData (result: number) { + getActions().onRecoverWalletData(result) +} + function promotionFinish (properties: Rewards.PromotionFinish) { getActions().onPromotionFinish(properties) } @@ -96,6 +114,34 @@ function adsData (adsData: Rewards.AdsData) { getActions().onAdsData(adsData) } +function adsHistory (adsHistory: Rewards.AdsHistory[]) { + getActions().onAdsHistory(adsHistory) +} + +function onToggleAdThumbUp (result: Rewards.ToggleLikeAction) { + getActions().onToggleAdThumbUp(result) +} + +function onToggleAdThumbDown (result: Rewards.ToggleLikeAction) { + getActions().onToggleAdThumbDown(result) +} + +function onToggleAdOptIn (result: Rewards.ToggleOptAction) { + getActions().onToggleAdOptIn(result) +} + +function onToggleAdOptOut (result: Rewards.ToggleOptAction) { + getActions().onToggleAdOptOut(result) +} + +function onToggleSavedAd (result: Rewards.ToggleSavedAd) { + getActions().onToggleSavedAd(result) +} + +function onToggleFlaggedAd (result: Rewards.ToggleFlaggedAd) { + getActions().onToggleFlaggedAd(result) +} + function onPendingContributionSaved (result: number) { if (result === 0) { getActions().getPendingContributions() @@ -118,6 +164,10 @@ function recurringTipRemoved (success: boolean) { getActions().onRecurringTipRemoved(success) } +function externalWalletProviderList (list: Rewards.ExternalWalletProvider[]) { + getActions().onExternalWalletProviderList(list) +} + function pendingContributions (list: Rewards.PendingContribution[]) { getActions().onPendingContributions(list) } @@ -147,6 +197,28 @@ function reconcileComplete (properties: {type: number, result: number}) { if (properties.type === 8) { // Rewards.RewardsType.ONE_TIME_TIP chrome.send('brave_rewards.getOneTimeTips') } + + // EXPIRED TOKEN + if (properties.result === 24) { + getActions().getExternalWallet() + } +} + +function externalWallet (properties: {result: number, wallet: Rewards.ExternalWallet}) { + getActions().onExternalWallet(properties.result, properties.wallet) +} + +function processRewardsPageUrl (data: Rewards.ProcessRewardsPageUrl) { + getActions().onProcessRewardsPageUrl(data) +} + +function disconnectWallet (properties: {result: number}) { + if (properties.result === 0) { + getActions().getExternalWallet() + getActions().getBalance() + return + } + getActions().disconnectWalletError() } function onlyAnonWallet (only: boolean) { @@ -157,10 +229,50 @@ function unblindedTokensReady () { getActions().getBalance() } +function monthlyReport (properties: { result: number, month: number, year: number, report: Rewards.MonthlyReport}) { + getActions().onMonthlyReport(properties) +} + +function reconcileStampReset () { + getActions().onReconcileStampReset() +} + +function monthlyReportIds (ids: string[]) { + getActions().onMonthlyReportIds(ids) +} + +function countryCode (countryCode: string) { + getActions().onCountryCode(countryCode) +} + function initialized (result: number) { getActions().onInitialized(result) } +function completeReset (success: boolean) { + getActions().onCompleteReset(success) +} + +function paymentId (paymentId: string) { + getActions().onPaymentId(paymentId) +} + +function walletPassphrase (passphrase: string) { + getActions().onWalletPassphrase(passphrase) +} + +function onboardingStatus (result: { showOnboarding: boolean }) { + getActions().onOnboardingStatus(result.showOnboarding) +} + +function enabledInlineTippingPlatforms (list: string[]) { + getActions().onEnabledInlineTippingPlatforms(list) +} + +function externalWalletLogin (url: string) { + window.open(url, '_self') +} + function onPrefChanged (key: string) { getActions().onPrefChanged(key) } @@ -171,9 +283,12 @@ function onPrefChanged (key: string) { window.brave_rewards = { rewardsParameters, promotions, + claimPromotion, + recoverWalletData, promotionFinish, reconcileStamp, contributeList, + externalWalletProviderList, excludedList, balanceReport, contributionAmount, @@ -181,6 +296,13 @@ window.brave_rewards = { currentTips, autoContributeProperties, adsData, + adsHistory, + onToggleAdThumbUp, + onToggleAdThumbDown, + onToggleAdOptIn, + onToggleAdOptOut, + onToggleSavedAd, + onToggleFlaggedAd, pendingContributions, onPendingContributionSaved, statement, @@ -191,9 +313,22 @@ window.brave_rewards = { excludedSiteChanged, balance, reconcileComplete, + externalWallet, + processRewardsPageUrl, + disconnectWallet, onlyAnonWallet, unblindedTokensReady, + monthlyReport, + reconcileStampReset, + monthlyReportIds, + countryCode, initialized, + completeReset, + paymentId, + walletPassphrase, + onboardingStatus, + enabledInlineTippingPlatforms, + externalWalletLogin, onPrefChanged } diff --git a/components/brave_rewards/resources/android_page/components/connect_wallet_modal.style.ts b/components/brave_rewards/resources/android_page/components/connect_wallet_modal.style.ts new file mode 100644 index 00000000000..84ae45f2576 --- /dev/null +++ b/components/brave_rewards/resources/android_page/components/connect_wallet_modal.style.ts @@ -0,0 +1,222 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import styled from 'styled-components' + +import warningCircleImage from '../../shared/assets/warning_circle.svg' +import greenCheckIcon from '../assets/green_check.svg' + +export const root = styled.div` + font-family: var(--brave-font-heading); + width: 880px; + min-height: 545px; + background: var(--brave-palette-white); + box-shadow: 0px 0px 16px rgba(99, 105, 110, 0.2); + border-radius: 8px; + display: flex; + overflow: hidden; + + a { + color: var(--brave-color-brandBat); + text-decoration: none; + } + + @media screen and (max-width: 700px) { + width: 380px; + min-height: 245px; + } +` + +export const leftPanel = styled.div` + flex: 0 1 448px; + padding: 70px 28px 31px 80px; + + @media screen and (max-width: 700px) { + padding: 50px 28px 31px 50px; + } +` + +export const rightPanel = styled.div` + flex: 1 1 auto; + padding: 32px 42px; + background: var(--brave-palette-neutral000); +` + +export const panelHeader = styled.div` + font-weight: 600; + font-size: 22px; + line-height: 28px; + color: var(--brave-palette-black); +` + +export const panelText = styled.div` + font-size: 14px; + line-height: 24px; + color: var(--brave-palette-neutral700); + margin-top: 8px; +` + +export const infoPanel = styled.div`` + +export const infoListItem = styled.div` + color: var(--brave-palette-neutral900); + font-weight: 600; + margin-top: 16px; + background: top 4px left no-repeat url("${greenCheckIcon}"); + padding-left: 23px; +` + +export const infoNote = styled.div` + color: var(--brave-palette-neutral600); + font-size: 12px; + line-height: 18px; + margin-top: 16px; +` + +export const continueButton = styled.div` + margin-top: 16px; + + button { + font-weight: 600; + font-size: 13px; + line-height: 19px; + cursor: pointer; + border: none; + outline-style: none; + + color: var(--brave-palette-white); + background: var(--brave-color-brandBat); + padding: 10px 39px; + border-radius: 20px; + + .icon { + height: 12px; + vertical-align: middle; + margin: 0 -6px 2px 2px; + } + + &:focus-visible { + outline-style: auto; + } + + &:active { + background: var(--brave-color-brandBatActive); + } + } +` + +export const infoTerms = styled.div` + font-size: 12px; + line-height: 18px; + color: var(--brave-palette-neutral600); + margin-top: 38px; + + strong { + font-weight: 600; + } +` + +export const connectGraphic = styled.div` + text-align: center; + margin: 86px auto 0; + width: 250px; +` + +export const minimumBalanceWarning = styled.div` + margin-top: 16px; + background: var(--brave-palette-neutral000); + border-radius: 8px; + padding: 16px 17px 26px 41px; + font-size: 14px; + line-height: 22px; + + background-repeat: no-repeat; + background-position: 17px 21px; + background-size: 16px 16px; + background-image: url('${warningCircleImage}'); + + .login { + margin-top: 8px; + font-weight: 600; + } +` + +export const selectWalletLeftPanel = styled.div` + margin-top: 30px; +` + +export const selectWalletContent = styled.div` + min-height: 236px; +` + +export const selectWalletNote = styled.div` + margin-top: 48px; + font-size: 12px; + line-height: 18px; + color: var(--brave-palette-neutral600); +` + +export const providerButtons = styled.div` + min-height: 72%; + padding-top: 40px; + display: flex; + flex-direction: column; + justify-content: center; + + button { + margin-bottom: 17px; + margin-left: 21px; + height: 79px; + display: flex; + align-items: center; + background: var(--brave-palette-white); + border: 2px solid var(--brave-palette-grey200); + border-radius: 8px; + font-weight: 600; + font-size: 16px; + line-height: 28px; + color: var(--brave-palette-black); + padding: 14px 20px; + cursor: pointer; + + &:active { + border-color: var(--brave-palette-grey300); + } + + &.selected { + border-color: var(--brave-color-brandBat); + } + } +` + +export const providerButtonIcon = styled.div` + flex: 0 0 52px; + background: rgb(218, 220, 232, .33); + border-radius: 50%; + height: 52px; + width: 52px; + padding: 14px 0; + + .icon { + height: 25px; + width: auto; + } +` + +export const providerButtonName = styled.div` + flex: 1 1 auto; + padding-left: 30px; + text-align: left; +` + +export const providerButtonCaret = styled.div` + flex: 0 0 10px; + + .icon { + height: 16px; + width: auto; + vertical-align: middle; + margin-bottom: 3px; + } +` diff --git a/components/brave_rewards/resources/android_page/components/connect_wallet_modal.tsx b/components/brave_rewards/resources/android_page/components/connect_wallet_modal.tsx new file mode 100644 index 00000000000..f8005d914b5 --- /dev/null +++ b/components/brave_rewards/resources/android_page/components/connect_wallet_modal.tsx @@ -0,0 +1,201 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +import { LocaleContext, formatMessage } from '../../shared/lib/locale_context' +import { Modal, ModalCloseButton } from '../../shared/components/modal' +import { CaretIcon } from '../../shared/components/icons/caret_icon' +import { GeminiIcon } from '../../shared/components/icons/gemini_icon' +import { UpholdIcon } from '../../shared/components/icons/uphold_icon' +import { BitflyerIcon } from '../../shared/components/icons/bitflyer_icon' + +import * as style from './connect_wallet_modal.style' + +export function getMinimumBalance (provider: string) { + switch (provider) { + case 'uphold': return 15 + default: return 0 + } +} + +function renderProviderIcon (provider: string) { + switch (provider) { + case 'bitflyer': return + case 'gemini': return + case 'uphold': return + default: return null + } +} + +type ModalState = 'info' | 'select' + +interface ExternalWalletProvider { + type: string + name: string +} + +interface Props { + rewardsBalance: number + providers: ExternalWalletProvider[] + onContinue: (provider: string) => void + onClose: () => void +} + +export function ConnectWalletModal (props: Props) { + const { getString } = React.useContext(LocaleContext) + + const [modalState, setModalState] = React.useState('info') + const [selectedProvider, setSelectedProvider] = + React.useState(null) + const [showMinimumBalanceWarning, setShowMinimumBalanceWarning] = + React.useState(false) + + if (props.providers.length === 0) { + return null + } + + function renderInfo () { + const onContinueClick = () => { + setModalState('select') + } + + return { + left: ( + + + {getString('connectWalletInfoHeader')} + + + {getString('connectWalletInfoText')} + + {getString('connectWalletInfoListItem1')} + + + {getString('connectWalletInfoListItem2')} + + + + {getString('connectWalletInfoNote')} + + + + + + { + formatMessage(getString('connectWalletInfoBraveNote'), { + tags: { + $1: (content) => {content} + } + }) + } + + + ), + right: null + } + } + + function renderMinimumBalanceWarning () { + const onLoginLinkClicked = (evt: React.MouseEvent) => { + evt.preventDefault() + if (selectedProvider) { + props.onContinue(selectedProvider.type) + } + } + + if (!selectedProvider) { + return null + } + + return ( + + { + formatMessage(getString('minimumBalanceWarning'), [ + selectedProvider.name, + getMinimumBalance(selectedProvider.type) + ]) + } + + + ) + } + + function renderSelectWallet () { + return { + left: null, + right: ( + + { showMinimumBalanceWarning && renderMinimumBalanceWarning() } + { + props.providers.map((provider) => { + const onClick = () => { + setSelectedProvider(provider) + if (props.rewardsBalance < getMinimumBalance(provider.type)) { + setShowMinimumBalanceWarning(true) + } else { + setShowMinimumBalanceWarning(false) + props.onContinue(provider.type) + } + } + + const selected = + selectedProvider && + provider.type === selectedProvider.type + + return ( + + ) + }) + } + + ) + } + } + + const { left, right } = modalState === 'info' + ? renderInfo() + : renderSelectWallet() + + return ( + + + { + left && + + + {left} + + } + { + right && + + + {right} + + } + + + ) +} diff --git a/components/brave_rewards/resources/android_page/components/contributeBox.tsx b/components/brave_rewards/resources/android_page/components/contributeBox.tsx index 909b3b31488..359da59ace7 100644 --- a/components/brave_rewards/resources/android_page/components/contributeBox.tsx +++ b/components/brave_rewards/resources/android_page/components/contributeBox.tsx @@ -225,7 +225,8 @@ class ContributeBox extends React.Component { enabledContribute, reconcileStamp, autoContributeList, - excludedList + excludedList, + externalWallet } = this.props.rewardsData const monthlyList: MonthlyChoice[] = utils.generateContributionMonthly(parameters) const contributeRows = this.getContributeRows(autoContributeList) @@ -235,6 +236,11 @@ class ContributeBox extends React.Component { const numExcludedRows = excludedRows && excludedRows.length const allSites = !(excludedRows.length > 0 || numRows > 5) + // Hide AC options from bitFlyer wallet regions. + if (externalWallet && externalWallet.type === 'bitflyer') { + return null + } + return ( { { this.state.modalContribute ? : null } diff --git a/components/brave_rewards/resources/android_page/components/icons/manage_wallet_icon.tsx b/components/brave_rewards/resources/android_page/components/icons/manage_wallet_icon.tsx new file mode 100644 index 00000000000..4d82891a0df --- /dev/null +++ b/components/brave_rewards/resources/android_page/components/icons/manage_wallet_icon.tsx @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +export function ManageWalletIcon () { + return ( + + + + ) +} diff --git a/components/brave_rewards/resources/android_page/components/manage_wallet_button.style.ts b/components/brave_rewards/resources/android_page/components/manage_wallet_button.style.ts new file mode 100644 index 00000000000..855249d5f34 --- /dev/null +++ b/components/brave_rewards/resources/android_page/components/manage_wallet_button.style.ts @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import styled from 'styled-components' + +import { buttonReset } from '../../shared/lib/css_mixins' + +export const root = styled.div` + margin: 10px 20px 0px; + + button { + ${buttonReset} + width: 100%; + font-family: var(--brave-font-heading); + font-weight: 600; + font-size: 13px; + line-height: 20px; + color: var(--brave-palette-neutral900); + border: 1px solid var(--brave-palette-grey500); + border-radius: 48px; + padding: 6px 18px; + cursor: pointer; + + &:active { + background: rgba(0, 0, 0, .01); + } + } + + .icon { + width: 17px; + height: auto; + vertical-align: middle; + margin-right: 8px; + margin-bottom: 3px; + } +` diff --git a/components/brave_rewards/resources/android_page/components/manage_wallet_button.tsx b/components/brave_rewards/resources/android_page/components/manage_wallet_button.tsx new file mode 100644 index 00000000000..7c6061f7299 --- /dev/null +++ b/components/brave_rewards/resources/android_page/components/manage_wallet_button.tsx @@ -0,0 +1,25 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import * as React from 'react' + +import { LocaleContext } from '../../shared/lib/locale_context' +import { ManageWalletIcon } from './icons/manage_wallet_icon' + +import * as style from './manage_wallet_button.style' + +interface Props { + onClick: () => void +} + +export function ManageWalletButton (props: Props) { + const { getString } = React.useContext(LocaleContext) + return ( + + + + ) +} diff --git a/components/brave_rewards/resources/android_page/components/pageWallet.tsx b/components/brave_rewards/resources/android_page/components/pageWallet.tsx index 9a7216f5d26..4e4f67833ad 100644 --- a/components/brave_rewards/resources/android_page/components/pageWallet.tsx +++ b/components/brave_rewards/resources/android_page/components/pageWallet.tsx @@ -5,37 +5,49 @@ import * as React from 'react' import { bindActionCreators, Dispatch } from 'redux' import { connect } from 'react-redux' - // Components -import { AlertWallet } from '../../ui/components/walletWrapper' import { - WalletSummary, - WalletWrapper, - WalletEmpty + ModalActivity, + ModalBackupRestore, + ModalPending, + ModalQRCode } from '../../ui/components' -import { CloseStrokeIcon } from 'brave-ui/components/icons' -import { StyledWalletClose, StyledWalletOverlay, StyledWalletWrapper } from './style' - +import { WalletCard, ExternalWalletAction } from '../../shared/components/wallet_card' +import { ExternalWallet, ExternalWalletProvider, ExternalWalletStatus } from '../../shared/lib/external_wallet' +import { WalletAddIcon, WalletWithdrawIcon } from 'brave-ui/components/icons' +import { AlertWallet } from '../../ui/components/walletWrapper' +import { Provider } from '../../ui/components/profile' +import { DetailRow as PendingDetailRow, PendingType } from '../../ui/components/tablePending' // Utils -import { getLocale } from '../../../../common/locale' +import { getLocale, getLocaleWithTag } from '../../../../common/locale' import * as rewardsActions from '../actions/rewards_actions' import * as utils from '../utils' +import { ExtendedActivityRow, SummaryItem, SummaryType } from '../../ui/components/modalActivity' +import { DetailRow as TransactionRow } from '../../ui/components/tableTransactions' +import { ConnectWalletModal } from './connect_wallet_modal' +import { ManageWalletButton } from './manage_wallet_button' +import { PageWalletWrapper } from './style' interface State { activeTabId: number + modalActivity: boolean + modalPendingContribution: boolean + modalVerify: boolean + modalQRCode: boolean } interface Props extends Rewards.ComponentProps { - visible?: boolean - toggleAction: () => void } class PageWallet extends React.Component { constructor (props: Props) { super(props) - this.state = { - activeTabId: 0 + activeTabId: 0, + modalActivity: false, + modalPendingContribution: false, + modalVerify: false, + modalQRCode: false } } @@ -43,94 +55,869 @@ class PageWallet extends React.Component { return this.props.actions } + hasUserFunds () { + const { balance } = this.props.rewardsData + return balance && balance.wallets.anonymous > 0 + } + + componentDidMount () { + this.isBackupUrl() + this.isDisconnectUrl() + this.isVerifyUrl() + this.actions.getMonthlyReportIds() + chrome.send('brave_rewards.getExternalWalletProviders') + } + + onModalBackupClose = () => { + if (this.urlHashIs('#manage-wallet')) { + window.location.hash = '' + } + this.actions.onModalBackupClose() + } + + onModalBackupOpen = () => { + if (!this.props.rewardsData.recoveryKey || this.props.rewardsData.recoveryKey.length === 0) { + this.actions.getWalletPassphrase() + } + this.actions.onModalBackupOpen() + } + + showBackupNotice = () => { + return this.state.activeTabId === 0 && !this.hasUserFunds() + } + + onModalBackupTabChange = (newTabId: number) => { + this.setState({ + activeTabId: newTabId + }) + } + + onModalBackupOnCopy = async (backupKey: string) => { + // TODO(jsadler) possibly flash a message that copy was completed + try { + await navigator.clipboard.writeText(backupKey) + console.log('Copy successful') + chrome.send('brave_rewards.setBackupCompleted') + } catch (e) { + console.log('Copy failed') + } + } + + onModalBackupOnPrint = (backupKey: string) => { + if (document.location) { + const win = window.open(document.location.href) + if (win) { + win.document.body.innerText = utils.constructBackupString(backupKey) // this should be text, not HTML + win.print() + win.close() + chrome.send('brave_rewards.setBackupCompleted') + } + } + } + + onModalBackupOnSaveFile = (backupKey: string) => { + const backupString = utils.constructBackupString(backupKey) + const backupFileText = 'brave_wallet_recovery.txt' + const a = document.createElement('a') + document.body.appendChild(a) + a.style.display = 'display: none' + const blob = new Blob([backupString], { type: 'plain/text' }) + const url = window.URL.createObjectURL(blob) + a.href = url + a.download = backupFileText + a.click() + window.URL.revokeObjectURL(url) + chrome.send('brave_rewards.setBackupCompleted') + } + + onModalBackupOnRestore = (key: string | MouseEvent) => { + if (typeof key === 'string' && key.length > 0) { + key = this.pullRecoveryKeyFromFile(key) + this.actions.recoverWallet(key) + } + } + + onModalBackupOnReset = () => { + this.actions.onModalBackupClose() + this.actions.completeReset() + } + + pullRecoveryKeyFromFile = (key: string) => { + let recoveryKey = null + if (key) { + let messageLines = key.match(/^.+$/gm) + if (messageLines) { + let passphraseLine = '' || messageLines[2] + if (passphraseLine) { + const passphrasePattern = new RegExp(['Recovery Key:', '(.+)$'].join(' ')) + recoveryKey = (passphraseLine.match(passphrasePattern) || [])[1] + return recoveryKey + } + } + } + return key + } + + onModalBackupOnImport = () => { + // TODO NZ implement + console.log('onModalBackupOnImport') + } + getConversion = () => { const { balance, parameters } = this.props.rewardsData return utils.convertBalance(balance.total, parameters.rate) } + onModalActivityToggle = () => { + if (!this.state.modalActivity) { + this.actions.getMonthlyReport() + } + + this.setState({ + modalActivity: !this.state.modalActivity + }) + } + + urlHashIs = (hash: string) => { + return ( + window && + window.location && + window.location.hash && + window.location.hash === hash + ) + } + + onModalPendingToggle = () => { + this.setState({ + modalPendingContribution: !this.state.modalPendingContribution + }) + } + + isBackupUrl = () => { + if (this.urlHashIs('#manage-wallet')) { + this.onModalBackupOpen() + } + } + + isVerifyUrl = () => { + if (this.urlHashIs('#verify')) { + this.toggleVerifyModal() + } + } + + isDisconnectUrl = () => { + if (this.urlHashIs('#disconnect-wallet')) { + this.actions.disconnectWallet() + } + } + + toggleVerifyModal = () => { + if (this.state.modalVerify) { + window.history.replaceState({}, 'Rewards', '/') + } + this.setState({ + modalVerify: !this.state.modalVerify + }) + } + + toggleQRCodeModal = () => { + // If we are opening the QR code panel, then request a payment ID if we do + // not already have one and close the backup/restore modal. + if (!this.state.modalQRCode) { + if (!this.props.rewardsData.paymentId) { + this.actions.getPaymentId() + } + this.actions.onModalBackupClose() + } + + this.setState({ + modalQRCode: !this.state.modalQRCode + }) + } + + onModalActivityAction = (action: string, value: string, node: any) => { + if (action === 'onMonthChange') { + const items = value.split('_') + if (items.length !== 2) { + return + } + this.actions.getMonthlyReport(parseInt(items[1], 10), parseInt(items[0], 10)) + } + } + walletAlerts = (): AlertWallet | null => { - const { walletServerProblem } = this.props.rewardsData.ui + const { + disconnectWalletError, + walletRecoveryStatus, + walletServerProblem + } = this.props.rewardsData.ui if (walletServerProblem) { return { - node: {getLocale('uhOh')} {getLocale('serverNotResponding')}, + node: <>{getLocale('uhOh')} {getLocale('serverNotResponding')}, type: 'error' } } + if (walletRecoveryStatus === 0) { + return { + node: <>{getLocale('walletRestored')} {getLocale('walletRecoverySuccess')}, + type: 'success', + onAlertClose: () => { + this.actions.onClearAlert('walletRecoveryStatus') + } + } + } + + const { externalWallet } = this.props.rewardsData + if (externalWallet && disconnectWalletError) { + return { + node: <>{getLocale('uhOh')}
{getLocale('disconnectWalletFailed').replace('$1', utils.getWalletProviderName(externalWallet))}

{getLocale('learnMore')}, + type: 'error', + onAlertClose: () => { + this.actions.onClearAlert('disconnectWalletError') + } + } + } + return null } - getWalletSummary = () => { - const { balanceReport, parameters } = this.props.rewardsData + getPendingRows = (): PendingDetailRow[] => { + const { parameters, pendingContributions } = this.props.rewardsData + return pendingContributions.map((item: Rewards.PendingContribution) => { + const verified = utils.isPublisherConnectedOrVerified(item.status) + let faviconUrl = `chrome://favicon/size/64@1x/${item.url}` + if (item.favIcon && verified) { + faviconUrl = `chrome://favicon/size/64@1x/${item.favIcon}` + } - let props = {} + let type: PendingType = 'ac' - if (balanceReport) { - for (let key in balanceReport) { - const item = balanceReport[key] + if (item.type === 8) { // one-time tip + type = 'tip' + } else if (item.type === 16) { // recurring tip + type = 'recurring' + } - if (item !== 0) { - const tokens = item.toFixed(3) - props[key] = { - tokens, - converted: utils.convertBalance(item, parameters.rate) - } + return { + profile: { + name: item.name, + verified, + provider: (item.provider ? item.provider : undefined) as Provider, + src: faviconUrl + }, + url: item.url, + type, + amount: { + tokens: item.amount.toFixed(3), + converted: utils.convertBalance(item.amount, parameters.rate) + }, + date: new Date(parseInt(item.expirationDate, 10) * 1000).toLocaleDateString(), + onRemove: () => { + this.actions.removePendingContribution(item.id) } } + }) + } + + removeAllPendingContribution = () => { + this.actions.removeAllPendingContribution() + } + + handleExternalWalletLink = () => { + const { externalWallet } = this.props.rewardsData + + if (!externalWallet) { + return + } + + if (externalWallet.status === 0) { + this.toggleVerifyModal() + return + } + + if (externalWallet.status === 1) { + window.open(externalWallet.verifyUrl, '_self') + return + } + + if (externalWallet.loginUrl) { + window.open(externalWallet.loginUrl, '_self') + } + } + + onConnectWalletContinue = (provider: string) => { + chrome.send('brave_rewards.setExternalWalletType', [provider]) + } + + onVerifyClick = () => { + const { externalWallet } = this.props.rewardsData + + if (!externalWallet || !externalWallet.loginUrl) { + this.actions.getExternalWallet() + return + } + + this.handleExternalWalletLink() + } + + getExternalWalletStatus = (): ExternalWalletStatus | null => { + const { externalWallet } = this.props.rewardsData + if (!externalWallet) { + return null + } + + switch (externalWallet.status) { + // ledger::type::WalletStatus::CONNECTED + case 1: + // WalletStatus::VERIFIED + case 2: + return 'verified' + // WalletStatus::DISCONNECTED_NOT_VERIFIED + case 3: + // WalletStatus::DISCONNECTED_VERIFIED + case 4: + return 'disconnected' + // ledger::type::WalletStatus::PENDING + case 5: + return 'pending' + default: + return null + } + } + + getExternalWalletProvider = (): ExternalWalletProvider | null => { + const { externalWallet } = this.props.rewardsData + if (!externalWallet) { + return null + } + + switch (externalWallet.type) { + case 'bitflyer': return 'bitflyer' + case 'gemini': return 'gemini' + case 'uphold': return 'uphold' + default: return null + } + } + + onFundsAction = (action: string) => { + const { externalWallet } = this.props.rewardsData + + if (!externalWallet) { + return + } + + switch (action) { + case 'add': { + if (externalWallet.addUrl) { + window.open(externalWallet.addUrl, '_self') + return + } + break + } + case 'withdraw': { + if (externalWallet.withdrawUrl) { + window.open(externalWallet.withdrawUrl, '_self') + return + } + break + } + } + + if (externalWallet.loginUrl) { + this.handleExternalWalletLink() + } + } + + goToExternalWallet = () => { + const { externalWallet } = this.props.rewardsData + + if (!externalWallet || !externalWallet.accountUrl) { + this.actions.getExternalWallet() + return + } + + window.open(externalWallet.accountUrl, '_self') + } + + getGreetings = () => { + const { externalWallet } = this.props.rewardsData + if (!externalWallet || !externalWallet.userName) { + return '' + } + + return getLocale('greetingsVerified', { name: externalWallet.userName }) + } + + onDisconnectClick = () => { + this.actions.disconnectWallet() + } + + getActions = () => { + return [ + { + name: getLocale('panelAddFunds'), + action: this.onFundsAction.bind(this, 'add'), + icon: , + testId: 'panel-add-funds', + externalWallet: true + }, + { + name: getLocale('panelWithdrawFunds'), + action: this.onFundsAction.bind(this, 'withdraw'), + icon: , + testId: 'panel-withdraw-funds', + externalWallet: true + } + ] + } + + getBalanceToken = (key: string) => { + const { + monthlyReport, + parameters, + externalWallet + } = this.props.rewardsData + + let value = 0.0 + if (monthlyReport && monthlyReport.balance && monthlyReport.balance[key]) { + value = monthlyReport.balance[key] } return { - report: props + value: value.toFixed(3), + converted: utils.convertBalance(value, parameters.rate), + link: externalWallet && externalWallet.status === 2 /* VERIFIED */ && key === 'ads' ? externalWallet.activityUrl : undefined + } + } + + generateSummaryRows = (): SummaryItem[] => { + return [ + { + type: 'grant', + token: this.getBalanceToken('grant') + }, + { + type: 'ads', + token: this.getBalanceToken('ads') + }, + { + type: 'contribute', + token: this.getBalanceToken('contribute') + }, + { + type: 'monthly', + token: this.getBalanceToken('monthly') + }, + { + type: 'tip', + token: this.getBalanceToken('tips') + } + ] + } + + generateActivityRows = (): ExtendedActivityRow[] => { + const { + monthlyReport, + parameters + } = this.props.rewardsData + + if (!monthlyReport.contributions) { + return [] + } + + let records: ExtendedActivityRow[] = [] + + monthlyReport.contributions + .forEach((contribution: Rewards.ContributionReport) => { + records = contribution.publishers + .map((publisher: Rewards.Publisher): ExtendedActivityRow => { + let faviconUrl = `chrome://favicon/size/64@1x/${publisher.url}` + const verified = utils.isPublisherConnectedOrVerified(publisher.status) + if (publisher.favIcon && verified) { + faviconUrl = `chrome://favicon/size/64@1x/${publisher.favIcon}` + } + return { + profile: { + name: publisher.name, + verified, + provider: (publisher.provider ? publisher.provider : undefined) as Provider, + src: faviconUrl + }, + url: publisher.url, + amount: { + tokens: publisher.weight.toFixed(3), + converted: utils.convertBalance(publisher.weight, parameters.rate) + }, + type: this.getSummaryType(contribution.type), + date: contribution.created_at + } + }) + .concat(records) + }) + + return records + } + + getSummaryType = (type: Rewards.ReportType): SummaryType => { + switch (type) { + case 0: { // Rewards.ReportType.GRANT_UGP + return 'grant' + } + case 1: { // Rewards.ReportType.AUTO_CONTRIBUTION + return 'contribute' + } + case 3: { // Rewards.ReportType.GRANT_AD + return 'ads' + } + case 4: { // Rewards.ReportType.TIP_RECURRING + return 'monthly' + } + case 5: { // Rewards.ReportType.TIP + return 'tip' + } + } + + return 'contribute' + } + + getTransactionDescription = (transaction: Rewards.TransactionReport) => { + switch (transaction.type) { + case 0: { // Rewards.ReportType.GRANT_UGP + return getLocale('tokenGrantReceived') + } + case 3: { // Rewards.ReportType.GRANT_AD + return getLocale('adsGrantReceived') + } + } + + return '' + } + + getProcessorString = (processor: Rewards.Processor) => { + let text = '' + switch (processor) { + case 0: { // Rewards.Processor.NONE + text = '' + break + } + case 1: { // Rewards.Processor.BRAVE_TOKENS + text = getLocale('processorBraveTokens') + break + } + case 2: { // Rewards.Processor.UPHOLD + text = getLocale('processorUphold') + break + } + case 3: { // Rewards.Processor.BRAVE_USER_FUNDS + text = getLocale('processorBraveUserFunds') + break + } + case 4: { // Rewards.Processor.BITFLYER + text = getLocale('processorBitflyer') + break + } + case 5: { // Rewards.Processor.GEMINI + text = getLocale('processorGemini') + break + } + } + + if (text.length === 0) { + return '' + } + + return `(${text})` + } + + getContributionDescription = (contribution: Rewards.ContributionReport) => { + if (contribution.type === 1) { // Rewards.ReportType.AUTO_CONTRIBUTION + return getLocale( + 'autoContributeTransaction', + { processor: this.getProcessorString(contribution.processor) }) + } + + return '' + } + + generateTransactionRows = (): TransactionRow[] => { + const { + monthlyReport, + parameters + } = this.props.rewardsData + + if (!monthlyReport.transactions && !monthlyReport.contributions) { + return [] + } + + let transactions: TransactionRow[] = [] + + if (monthlyReport.transactions) { + transactions = monthlyReport.transactions.map((transaction: Rewards.TransactionReport) => { + return { + date: transaction.created_at, + type: this.getSummaryType(transaction.type), + description: this.getTransactionDescription(transaction), + amount: { + value: transaction.amount.toFixed(3), + converted: utils.convertBalance(transaction.amount, parameters.rate) + } + } + }) + } + + if (monthlyReport.contributions) { + transactions = transactions.concat( + monthlyReport.contributions + .filter((contribution: Rewards.ContributionReport) => contribution.type === 1) + .map((contribution: Rewards.ContributionReport) => { + return { + date: contribution.created_at, + type: this.getSummaryType(contribution.type), + description: this.getContributionDescription(contribution), + amount: { + value: contribution.amount.toFixed(3), + converted: utils.convertBalance(contribution.amount, parameters.rate), + isNegative: true + } + } + }) + ) + } + + transactions.sort((a, b) => a.date - b.date) + + return transactions + } + + getMonthlyReportDropDown = (): Record => { + const { monthlyReportIds } = this.props.rewardsData + + const ids = [ + `${new Date().getFullYear()}_${new Date().getMonth() + 1}`, + ...monthlyReportIds || [] + ] + + let result: Record = {} + ids.forEach((id: string) => { + const items = id.split('_') + if (items.length !== 2) { + return + } + + const year = parseInt(items[0], 10) + const month = parseInt(items[1], 10) - 1 + + // we only want to show reports from version 1.3 (Feb 2020) up + if (year < 2020 || (year === 2020 && month === 0)) { + return + } + + // Don't show drop-down items for a future month + if (new Date(year, month).getTime() > Date.now()) { + return + } + + const date = new Date(Date.UTC(year, month, 10)) + result[id] = new Intl.DateTimeFormat('default', { month: 'long', year: 'numeric' }).format(date) + }) + + return result + } + + generateMonthlyReport = () => { + const { monthlyReport, externalWallet } = this.props.rewardsData + + if (!monthlyReport || monthlyReport.year === -1 || monthlyReport.month === -1) { + return undefined + } + + return ( + + ) + } + + getInternalFunds = () => { + const { balance } = this.props.rewardsData + if (!balance.wallets) { + return 0 + } + + return (balance.wallets.anonymous || 0) + (balance.wallets.blinded || 0) + } + + getBackupErrorMessage = () => { + const { ui } = this.props.rewardsData + const { walletRecoveryStatus } = ui + + if (walletRecoveryStatus === null) { + return '' + } + + // ledger::type::Result::CORRUPTED_DATA + if (walletRecoveryStatus === 17) { + const tags = getLocaleWithTag('walletRecoveryOutdated') + return ( + + {tags.beforeTag} + + {tags.duringTag} + + {tags.afterTag} + + ) + } + + if (walletRecoveryStatus !== 0) { + return getLocale('walletRecoveryFail') + } + + return '' + } + + generateExternalWalletProviderList = (walletProviders: string[]) => { + return walletProviders.map((type) => ({ type, name: utils.getWalletProviderName(type) })) + } + + onExternalWalletAction = (action: ExternalWalletAction) => { + switch (action) { + case 'add-funds': + this.onFundsAction('add') + break + case 'complete-verification': + this.handleExternalWalletLink() + break + case 'disconnect': + this.onDisconnectClick() + break + case 'reconnect': + this.handleExternalWalletLink() + break + case 'verify': + this.onVerifyClick() + break + case 'view-account': + this.goToExternalWallet() + break } } render () { - const { visible, toggleAction } = this.props const { + adsData, balance, + balanceReport, + enabledContribute, + externalWalletProviderList, ui, + recoveryKey, + externalWallet, + parameters, + paymentId, pendingContributionTotal } = this.props.rewardsData - const { emptyWallet } = ui const { total } = balance - const pendingTotal = parseFloat((pendingContributionTotal || 0).toFixed(3)) + const { modalBackup } = ui - if (!visible) { - return null + let externalWalletInfo: ExternalWallet | null = null + const walletStatus = this.getExternalWalletStatus() + const walletProvider = this.getExternalWalletProvider() + if (externalWallet && walletStatus && walletProvider) { + externalWalletInfo = { + provider: walletProvider, + status: walletStatus, + username: externalWallet.userName || '', + links: {} + } + } + + const summaryData = { + adEarnings: balanceReport && balanceReport.ads || 0, + autoContributions: balanceReport && balanceReport.contribute || 0, + oneTimeTips: balanceReport && balanceReport.tips || 0, + monthlyTips: balanceReport && balanceReport.monthly || 0, + pendingTips: pendingContributionTotal || 0 } return ( - - - - - - - - { - emptyWallet - ? - : - } - - - - + + + + { + modalBackup + ? + : null + } + { + this.state.modalPendingContribution + ? + : null + } + { + this.state.modalVerify + ? + : null + } + { + this.state.modalActivity + ? this.generateMonthlyReport() + : null + } + { + this.state.modalQRCode + ? + : null + } + ) } } diff --git a/components/brave_rewards/resources/android_page/components/settingsPage.tsx b/components/brave_rewards/resources/android_page/components/settingsPage.tsx index db37e9a8a7b..7e620dc432c 100644 --- a/components/brave_rewards/resources/android_page/components/settingsPage.tsx +++ b/components/brave_rewards/resources/android_page/components/settingsPage.tsx @@ -7,31 +7,31 @@ import { bindActionCreators, Dispatch } from 'redux' import { connect } from 'react-redux' // Components -import Promotion from './promotion' +import { + MainToggleMobile, + SettingsPageMobile as Page +} from '../../ui/components/mobile' +import { ModalRedirect } from '../../ui/components' + +import PageWallet from './pageWallet' import AdsBox from './adsBox' import ContributeBox from './contributeBox' import TipBox from './tipsBox' -import PageWallet from './pageWallet' import MonthlyContributionBox from './monthlyContributionBox' -import { - MainToggleMobile, - SettingsPageMobile, - WalletInfoHeader -} from '../../ui/components/mobile' - -import { getLocale } from 'brave-ui/helpers' -import { AlertWallet } from '../../ui/components/mobile/walletInfoHeader' // Utils import * as rewardsActions from '../actions/rewards_actions' -import * as utils from '../utils' - -interface State { - walletShown: boolean -} +import Promotion from './promotion' +import { getLocale } from '../../../../common/locale' +import { getWalletProviderName } from '../utils' export interface Props extends Rewards.ComponentProps { - rewardsEnabled?: boolean +} + +interface State { + redirectModalDisplayed: 'hide' | 'show' + showRewardsTour: boolean + firstTimeSetup: boolean } class SettingsPage extends React.Component { @@ -40,7 +40,9 @@ class SettingsPage extends React.Component { constructor (props: Props) { super(props) this.state = { - walletShown: false + redirectModalDisplayed: 'hide', + showRewardsTour: false, + firstTimeSetup: false } } @@ -48,16 +50,6 @@ class SettingsPage extends React.Component { return this.props.actions } - onToggleWallet = () => { - if (this.state.walletShown) { - window.location.hash = '' - } else { - window.location.hash = '#rewards-summary' - } - - this.setState({ walletShown: !this.state.walletShown }) - } - refreshActions () { this.actions.getBalanceReport(new Date().getMonth() + 1, new Date().getFullYear()) this.actions.getTipTable() @@ -67,24 +59,16 @@ class SettingsPage extends React.Component { this.actions.getStatement() this.actions.getAdsData() this.actions.getExcludedSites() - this.actions.getExternalWallet() + this.actions.getCountryCode() } componentDidMount () { - if (this.props.rewardsData.firstLoad === null) { - // First load ever - this.actions.onSettingSave('firstLoad', true, false) - } else if (this.props.rewardsData.firstLoad) { - // Second load ever - this.actions.onSettingSave('firstLoad', false, false) - } - if (!this.props.rewardsData.initializing) { this.startRewards() } } - componentDidUpdate (prevProps: Props) { + componentDidUpdate (prevProps: Props, prevState: State) { if ( prevProps.rewardsData.initializing && !this.props.rewardsData.initializing @@ -101,38 +85,28 @@ class SettingsPage extends React.Component { } if ( - !prevProps.rewardsData.adsData.adsEnabled && - this.props.rewardsData.adsData.adsEnabled + prevState.redirectModalDisplayed !== 'hide' && + this.props.rewardsData.ui.modalRedirect === 'hide' ) { - this.actions.getStatement() - } - } - - startRewards () { - if (this.props.rewardsData.firstLoad) { - this.actions.getAdsData() - } else { - // normal load - this.refreshActions() + this.setState({ + redirectModalDisplayed: 'hide' + }) + window.history.replaceState({}, 'Rewards', '/') + } else if ( + prevState.redirectModalDisplayed === 'hide' && + this.props.rewardsData.ui.modalRedirect !== 'hide' + ) { + this.setState({ + redirectModalDisplayed: 'show' + }) } - this.actions.getRewardsParameters() - this.actions.getContributionAmount() - this.actions.getAutoContributeProperties() - this.actions.getBalance() - this.actions.getExternalWallet() - this.balanceTimerId = window.setInterval(() => { - this.actions.getBalance() - }, 60000) - - this.actions.fetchPromotions() - this.isWalletUrl() - window.addEventListener('popstate', (e) => { - this.isWalletUrl() - }) - window.addEventListener('hashchange', (e) => { - this.isWalletUrl() - }) + if ( + prevProps.rewardsData.externalWallet && + !this.props.rewardsData.externalWallet + ) { + this.actions.getExternalWallet() + } } stopRewards () { @@ -140,44 +114,52 @@ class SettingsPage extends React.Component { this.balanceTimerId = -1 } - isWalletUrl = () => { - const walletShown = ( - window && - window.location && - window.location.hash && - window.location.hash === '#rewards-summary' - ) + startRewards () { + this.refreshActions() - this.setState({ - walletShown: !!walletShown - }) + this.actions.getRewardsParameters() + this.actions.getContributionAmount() + this.actions.getAutoContributeProperties() + this.actions.getBalance() + this.balanceTimerId = window.setInterval(() => { + this.actions.getBalance() + }, 60000) + + this.actions.fetchPromotions() + this.actions.getExternalWallet() + this.actions.getOnboardingStatus() + this.actions.getEnabledInlineTippingPlatforms() + + this.handleURL() } - walletAlerts = (): AlertWallet | null => { - const { externalWallet } = this.props.rewardsData - const { disconnectWalletError } = this.props.rewardsData.ui + handleURL () { + const { pathname } = window.location - if (disconnectWalletError) { - return { - node: <>{getLocale('uhOh')}
{getLocale('disconnectWalletFailed').replace('$1', utils.getWalletProviderName(externalWallet))}

{getLocale('learnMore')}, - type: 'error', - onAlertClose: () => { - this.actions.onClearAlert('disconnectWalletError') - } + if (pathname === '/enable') { + this.actions.saveOnboardingResult('opted-in') + this.setState({ showRewardsTour: true, firstTimeSetup: true }) + window.history.replaceState({}, '', '/') + return + } + + if (pathname.length > 1) { + const pathElements = pathname.split('/') + if (pathElements.length > 2) { + this.actions.processRewardsPageUrl(window.location.pathname, window.location.search) } } - return null } getPromotionsClaims = () => { const { promotions } = this.props.rewardsData - if (!promotions) { + if (!promotions || promotions.length === 0) { return null } return ( -
+
{promotions.map((promotion?: Rewards.Promotion, index?: number) => { if (!promotion || !promotion.promotionId) { return null @@ -197,32 +179,159 @@ class SettingsPage extends React.Component { this.stopRewards() } - render () { - const { externalWallet, parameters, balance } = this.props.rewardsData - const { total } = balance - const convertedBalance = utils.convertBalance((total || 0), parameters.rate) + onRedirectError = () => { + this.actions.hideRedirectModal() + const { externalWallet } = this.props.rewardsData + + if (externalWallet && externalWallet.verifyUrl) { + window.open(externalWallet.verifyUrl, '_self') + } + } + + getRedirectModal = () => { + const { externalWallet, ui } = this.props.rewardsData + const walletType = externalWallet ? externalWallet.type : '' + + switch (ui.modalRedirect) { + case 'deviceLimitReachedModal': + return ( + + ) + case 'error': + return ( + + ) + case 'kycRequiredModal': + return ( + + ) + case 'mismatchedProviderAccountsModal': + return ( + + ) + case 'show': + return ( + + ) + case 'upholdBATNotAllowedModal': + return ( + + ) + case 'upholdBlockedUserModal': + return ( + + ) + case 'upholdPendingUserModal': + return ( + + ) + case 'upholdRestrictedUserModal': + return ( + + ) + default: + return null + } + } + + renderSettings () { return ( - + <> - {this.getPromotionsClaims()} - - - + + ) + } + + render () { + return ( + + {this.getPromotionsClaims()} + + {this.getRedirectModal()} + {this.renderSettings()} + ) } } diff --git a/components/brave_rewards/resources/android_page/components/style.ts b/components/brave_rewards/resources/android_page/components/style.ts index 36280d7b248..afe71d7444d 100644 --- a/components/brave_rewards/resources/android_page/components/style.ts +++ b/components/brave_rewards/resources/android_page/components/style.ts @@ -4,6 +4,18 @@ import styled from 'styled-components' +export const TourPromoWrapper = styled('div')<{}>` + margin-top: 30px; +` + +export const PageWalletWrapper = styled.div` + width: 373px; + + @media screen and (max-width: 700px) { + margin-bottom: 10px; + } +` + export const StyledListContent = styled('div')<{}>` padding: 0 25px; ` diff --git a/components/brave_rewards/resources/android_page/constants/rewards_types.ts b/components/brave_rewards/resources/android_page/constants/rewards_types.ts index e5e9b6b2afb..949a252cb5d 100644 --- a/components/brave_rewards/resources/android_page/constants/rewards_types.ts +++ b/components/brave_rewards/resources/android_page/constants/rewards_types.ts @@ -12,8 +12,13 @@ export const enum types { FETCH_PROMOTIONS = '@@rewards/FETCH_PROMOTIONS', ON_PROMOTIONS = '@@rewards/ON_PROMOTION', CLAIM_PROMOTION = '@@rewards/CLAIM_PROMOTION', + ON_CLAIM_PROMOTION = '@@rewards/ON_CLAIM_PROMOTION', + ATTEST_PROMOTION = '@@rewards/ATTEST_PROMOTION', + RESET_PROMOTION = '@@rewards/RESET_PROMOTION', DELETE_PROMOTION = '@@rewards/DELETE_PROMOTION', ON_PROMOTION_FINISH = '@@rewards/ON_PROMOTION_FINISH', + RECOVER_WALLET = '@@rewards/RECOVER_WALLET', + ON_RECOVER_WALLET_DATA = '@@rewards/ON_RECOVER_WALLET_DATA', ON_MODAL_BACKUP_CLOSE = '@@rewards/ON_MODAL_BACKUP_CLOSE', ON_MODAL_BACKUP_OPEN = '@@rewards/ON_MODAL_BACKUP_OPEN', ON_CLEAR_ALERT = '@@rewards/ON_CLEAR_ALERT', @@ -32,6 +37,20 @@ export const enum types { INIT_AUTOCONTRIBUTE_SETTINGS = '@@rewards/INIT_AUTOCONTRIBUTE_SETTINGS', GET_ADS_DATA = '@@rewards/GET_ADS_DATA', ON_ADS_DATA = '@@rewards/ON_ADS_DATA', + GET_ADS_HISTORY = '@@rewards/GET_ADS_HISTORY', + TOGGLE_AD_THUMB_UP = '@@rewards/TOGGLE_AD_THUMB_UP', + ON_TOGGLE_AD_THUMB_UP = '@@rewards/ON_TOGGLE_AD_THUMB_UP', + TOGGLE_AD_THUMB_DOWN = '@@rewards/TOGGLE_AD_THUMB_DOWN', + ON_TOGGLE_AD_THUMB_DOWN = '@@rewards/ON_TOGGLE_AD_THUMB_DOWN', + TOGGLE_AD_OPT_IN = '@@rewards/TOGGLE_AD_OPT_IN', + ON_TOGGLE_AD_OPT_IN = '@@rewards/ON_TOGGLE_AD_OPT_IN', + TOGGLE_AD_OPT_OUT = '@@rewards/TOGGLE_AD_OPT_OUT', + ON_TOGGLE_AD_OPT_OUT = '@@rewards/ON_TOGGLE_AD_OPT_OUT', + TOGGLE_SAVED_AD = '@@rewards/TOGGLE_SAVED_AD', + ON_TOGGLE_SAVED_AD = '@@rewards/ON_TOGGLE_SAVED_AD', + TOGGLE_FLAGGED_AD = '@@rewards/TOGGLE_FLAGGED_AD', + ON_TOGGLE_FLAGGED_AD = '@@rewards/ON_TOGGLE_FLAGGED_AD', + ON_ADS_HISTORY = '@@rewards/ON_ADS_HISTORY', ON_ADS_SETTING_SAVE = '@@rewards/ON_ADS_SETTING_SAVE', GET_BALANCE_REPORT = '@@rewards/GET_BALANCE_REPORT', ON_BALANCE_REPORT = '@@rewards/ON_BALANCE_REPORT', @@ -49,14 +68,38 @@ export const enum types { ON_EXCLUDED_LIST = '@@rewards/ON_EXCLUDED_LIST', ON_RESTORE_PUBLISHER = '@@rewards/ON_RESTORE_PUBLISHER', GET_EXCLUDED_SITES = '@@rewards/GET_EXCLUDED_SITES', - GET_EXTERNAL_WALLET = '@@rewards/GET_EXTERNAL_WALLET', GET_BALANCE = '@@rewards/GET_BALANCE', ON_BALANCE = '@@rewards/ON_BALANCE', + GET_EXTERNAL_WALLET = '@@rewards/GET_EXTERNAL_WALLET', ON_EXTERNAL_WALLET = '@@rewards/ON_EXTERNAL_WALLET', + PROCESS_REWARDS_PAGE_URL = '@@rewards/PROCESS_REWARDS_PAGE_URL', + ON_PROCESS_REWARDS_PAGE_URL = '@@rewards/ON_PROCESS_REWARDS_PAGE_URL', + HIDE_REDIRECT_MODAL = '@@rewards/HIDE_REDIRECT_MODAL', + DISCONNECT_WALLET = '@@rewards/DISCONNECT_WALLET', ONLY_ANON_WALLET = '@@rewards/ONLY_ANON_WALLET', ON_ONLY_ANON_WALLET = '@@rewards/ON_ONLY_ANON_WALLET', + GET_MONTHLY_REPORT = '@@rewards/GET_MONTHLY_REPORT', + ON_MONTHLY_REPORT = '@@rewards/ON_MONTHLY_REPORT', + ON_RECONCILE_STAMP_RESET = '@@rewards/ON_RECONCILE_STAMP_RESET', + GET_MONTHLY_REPORT_IDS = '@@rewards/GET_MONTHLY_REPORT_IDS', + ON_MONTHLY_REPORT_IDS = '@@rewards/ON_MONTHLY_REPORT_IDS', + DISMISS_PROMO_PROMPT = '@@rewards/DISMISS_PROMO_PROMPT', + GET_COUNTRY_CODE = '@@rewards/GET_COUNTRY_CODE', + ON_COUNTRY_CODE = '@@rewards/ON_COUNTRY_CODE', ON_INITIALIZED = '@@rewards/ON_INITIALIZED', - DISCONNECT_WALLET = '@@rewards/DISCONNECT_WALLET', + COMPLETE_RESET = '@@rewards/COMPLETE_RESET', + ON_COMPLETE_RESET = '@@rewards/ON_COMPLETE_RESET', + GET_PAYMENT_ID = '@@rewards/GET_PAYMENT_ID', + ON_PAYMENT_ID = '@@rewards/ON_PAYMENT_ID', + GET_WALLET_PASSPHRASE = '@@rewards/GET_WALLLET_PASSPHRASE', + ON_WALLET_PASSPHRASE = '@@rewards/ON_WALLLET_PASSPHRASE', + GET_ONBOARDING_STATUS = '@@rewards/GET_ONBOARDING_STATUS', + ON_ONBOARDING_STATUS = '@@rewards/ON_ONBOARDING_STATUS', + SAVE_ONBOARDING_RESULT = '@@rewards/SAVE_ONBOARDING_RESULT', DISCONNECT_WALLET_ERROR = '@@rewards/DISCONNECT_WALLET_ERROR', + GET_ENABLED_INLINE_TIPPING_PLATFORMS = '@@rewards/GET_ENABLED_INLINE_TIPPING_PLATFORMS', + ON_ENABLED_INLINE_TIPPING_PLATFORMS = '@@rewards/ON_ENABLED_INLINE_TIPPING_PLATFORMS', + ON_EXTERNAL_WALLET_PROVIDER_LIST = '@@rewards/ON_EXTERNAL_WALLET_PROVIDER_LIST', + RESTART_BROWSER = '@@rewards/RESTART_BROWSER', ON_PREF_CHANGED = '@@rewards/ON_PREF_CHANGED' } diff --git a/components/brave_rewards/resources/android_page/reducers/rewards_reducer.ts b/components/brave_rewards/resources/android_page/reducers/rewards_reducer.ts index 1834ff985da..98c085a1725 100644 --- a/components/brave_rewards/resources/android_page/reducers/rewards_reducer.ts +++ b/components/brave_rewards/resources/android_page/reducers/rewards_reducer.ts @@ -9,6 +9,10 @@ import { types } from '../constants/rewards_types' import { defaultState } from '../storage' const rewardsReducer: Reducer = (state: Rewards.State, action) => { + if (!state) { + return + } + switch (action.type) { case types.IS_INITIALIZED: { chrome.send('brave_rewards.isInitialized') @@ -18,11 +22,6 @@ const rewardsReducer: Reducer = (state: Rewards.State chrome.send('brave_rewards.getAutoContributeProperties') break } - case types.DISCONNECT_WALLET : { - state = { ...state } - chrome.send('brave_rewards.disconnectWallet') - break - } case types.DISCONNECT_WALLET_ERROR: { state = { ...state } let ui = state.ui @@ -53,34 +52,22 @@ const rewardsReducer: Reducer = (state: Rewards.State break } - case types.GET_EXTERNAL_WALLET: { - chrome.send('brave_rewards.getExternalWallet') - break - } - case types.ON_EXTERNAL_WALLET: { - state = { ...state } - - if (action.payload.result === 24) { // on ledger::type::Result::EXPIRED_TOKEN - chrome.send('brave_rewards.getExternalWallet') - break - } - - if (action.payload.result === 0) { // type::Result::LEDGER_OK - chrome.send('brave_rewards.fetchBalance') - } - - state.externalWallet = action.payload.wallet - break - } - case types.ON_SETTING_SAVE: + case types.ON_SETTING_SAVE: { state = { ...state } const key = action.payload.key const value = action.payload.value - if (key) { - state[key] = value + const persist = action.payload.persist + if (!key) { + break + } + + if (persist) { chrome.send('brave_rewards.saveSetting', [key, value.toString()]) } + + state[key] = value break + } case types.ON_MODAL_BACKUP_CLOSE: { state = { ...state } let ui = state.ui @@ -103,7 +90,7 @@ const rewardsReducer: Reducer = (state: Rewards.State } case types.ON_CLEAR_ALERT: { let ui = state.ui - if (!ui[action.payload.property]) { + if (ui[action.payload.property] === undefined) { break } @@ -152,16 +139,85 @@ const rewardsReducer: Reducer = (state: Rewards.State state.adsData.adsIsSupported = action.payload.adsData.adsIsSupported break } + case types.GET_ADS_HISTORY: { + chrome.send('brave_rewards.getAdsHistory') + break + } + case types.ON_ADS_HISTORY: { + if (!action.payload.adsHistory) { + break + } + + state = { ...state } + + if (!state.adsHistory) { + state.adsHistory = defaultState.adsHistory + } + + state.adsHistory = action.payload.adsHistory + break + } + case types.TOGGLE_AD_THUMB_UP: { + chrome.send('brave_rewards.toggleAdThumbUp', [action.payload.adContent]) + break + } + case types.ON_TOGGLE_AD_THUMB_UP: { + chrome.send('brave_rewards.getAdsHistory') + break + } + case types.TOGGLE_AD_THUMB_DOWN: { + chrome.send('brave_rewards.toggleAdThumbDown', [action.payload.adContent]) + break + } + case types.ON_TOGGLE_AD_THUMB_DOWN: { + chrome.send('brave_rewards.getAdsHistory') + break + } + case types.TOGGLE_AD_OPT_IN: { + chrome.send('brave_rewards.toggleAdOptIn', + [action.payload.category, action.payload.optAction]) + break + } + case types.ON_TOGGLE_AD_OPT_IN: { + chrome.send('brave_rewards.getAdsHistory') + break + } + case types.TOGGLE_AD_OPT_OUT: { + chrome.send('brave_rewards.toggleAdOptOut', + [action.payload.category, action.payload.optAction]) + break + } + case types.ON_TOGGLE_AD_OPT_OUT: { + chrome.send('brave_rewards.getAdsHistory') + break + } + case types.TOGGLE_SAVED_AD: { + chrome.send('brave_rewards.toggleSavedAd', [action.payload.adContent]) + break + } + case types.ON_TOGGLE_SAVED_AD: { + chrome.send('brave_rewards.getAdsHistory') + break + } + case types.TOGGLE_FLAGGED_AD: { + chrome.send('brave_rewards.toggleFlaggedAd', [action.payload.adContent]) + break + } + case types.ON_TOGGLE_FLAGGED_AD: { + chrome.send('brave_rewards.getAdsHistory') + break + } case types.ON_ADS_SETTING_SAVE: { state = { ...state } const key = action.payload.key const value = action.payload.value if (key) { - state[key] = value chrome.send('brave_rewards.saveAdsSetting', [key, value.toString()]) - if (key === 'adsEnabledMigrated') { state.enabledAdsMigrated = true + } else { + state.adsData = { ...(state.adsData || defaultState.adsData) } + state.adsData[key] = value } } break @@ -189,6 +245,38 @@ const rewardsReducer: Reducer = (state: Rewards.State state.adsData.adsEarningsLastMonth = data.adsEarningsLastMonth break } + case types.GET_ENABLED_INLINE_TIPPING_PLATFORMS: { + chrome.send('brave_rewards.getEnabledInlineTippingPlatforms') + break + } + case types.ON_ENABLED_INLINE_TIPPING_PLATFORMS: { + const inlineTip = { + twitter: false, + reddit: false, + github: false + } + + for (const platform of action.payload.platforms) { + switch (platform) { + case 'github': + inlineTip.github = true + break + case 'reddit': + inlineTip.reddit = true + break + case 'twitter': + inlineTip.twitter = true + break + } + } + + state = { + ...state, + inlineTip + } + + break + } case types.ON_INLINE_TIP_SETTINGS_CHANGE: { if (!state.inlineTip) { state.inlineTip = { @@ -217,6 +305,124 @@ const rewardsReducer: Reducer = (state: Rewards.State break } + case types.PROCESS_REWARDS_PAGE_URL: { + const path = action.payload.path + const query = action.payload.query + const ui = state.ui + + chrome.send('brave_rewards.processRewardsPageUrl', [path, query]) + ui.modalRedirect = 'show' + + state = { + ...state, + ui + } + break + } + case types.ON_PROCESS_REWARDS_PAGE_URL: { + const data = action.payload.data + const ui = state.ui + + chrome.send('brave_rewards.getExternalWallet') + + if (data.result === 9) { // type::Result::NOT_FOUND + ui.modalRedirect = 'kycRequiredModal' + break + } + + if (data.result === 24) { // type::Result::EXPIRED_TOKEN + ui.modalRedirect = 'error' + break + } + + if (data.result === 25) { // type::Result::UPHOLD_BAT_NOT_ALLOWED + ui.modalRedirect = 'upholdBATNotAllowedModal' + break + } + + if (data.result === 36) { // type::Result::DEVICE_LIMIT_REACHED + ui.modalRedirect = 'deviceLimitReachedModal' + break + } + + if (data.result === 37) { // type::Result::MISMATCHED_PROVIDER_ACCOUNTS + ui.modalRedirect = 'mismatchedProviderAccountsModal' + break + } + + if (data.result !== 0) { + ui.modalRedirect = 'error' + break + } + + if (data.walletType === 'uphold' || data.walletType === 'bitflyer' || data.walletType === 'gemini') { + chrome.send('brave_rewards.fetchBalance') + + if (data.action === 'authorization') { + const url = data.args.redirect_url + if (url && url.length > 0) { + window.open(url, '_self') + } + ui.modalRedirect = 'hide' + break + } + } + + ui.modalRedirect = 'error' + + state = { + ...state, + ui + } + break + } + case types.HIDE_REDIRECT_MODAL: { + const ui = state.ui + + ui.modalRedirect = 'hide' + + state = { + ...state, + ui + } + break + } + case types.DISCONNECT_WALLET: { + state = { ...state } + chrome.send('brave_rewards.disconnectWallet') + break + } + case types.GET_EXTERNAL_WALLET: { + chrome.send('brave_rewards.getExternalWallet') + break + } + case types.ON_EXTERNAL_WALLET: { + state = { ...state } + + if (action.payload.result === 24) { // on ledger::type::Result::EXPIRED_TOKEN + chrome.send('brave_rewards.getExternalWallet') + break + } + + if (action.payload.result === 0) { // type::Result::LEDGER_OK + chrome.send('brave_rewards.fetchBalance') + } + + state.externalWallet = action.payload.wallet + break + } + case types.GET_COUNTRY_CODE: { + chrome.send('brave_rewards.getCountryCode') + break + } + case types.ON_COUNTRY_CODE: { + const { countryCode } = action.payload + state = { + ...state, + currentCountryCode: countryCode + } + break + } case types.ON_INITIALIZED: { state = { ...state, @@ -225,6 +431,31 @@ const rewardsReducer: Reducer = (state: Rewards.State chrome.send('brave_rewards.getReconcileStamp') break } + case types.COMPLETE_RESET: { + chrome.send('brave_rewards.completeReset') + break + } + case types.ON_COMPLETE_RESET: { + if (action.payload.success) { + return undefined + } + break + } + case types.GET_PAYMENT_ID: { + chrome.send('brave_rewards.getPaymentId') + break + } + case types.ON_PAYMENT_ID: { + state = { + ...state, + paymentId: action.payload.paymentId + } + break + } + case types.RESTART_BROWSER: { + chrome.send('brave_rewards.restartBrowser') + break + } case types.ON_PREF_CHANGED: { chrome.send('brave_rewards.getEnabledInlineTippingPlatforms') chrome.send('brave_rewards.getContributionAmount') diff --git a/components/brave_rewards/resources/android_page/reducers/wallet_reducer.ts b/components/brave_rewards/resources/android_page/reducers/wallet_reducer.ts index 6b1065f0e00..832b0bd088a 100644 --- a/components/brave_rewards/resources/android_page/reducers/wallet_reducer.ts +++ b/components/brave_rewards/resources/android_page/reducers/wallet_reducer.ts @@ -4,24 +4,68 @@ import { Reducer } from 'redux' +import { getCurrentBalanceReport } from '../utils' + // Constant import { types } from '../constants/rewards_types' const walletReducer: Reducer = (state: Rewards.State, action) => { + if (!state) { + return + } + switch (action.type) { case types.GET_REWARDS_PARAMETERS: chrome.send('brave_rewards.getRewardsParameters') break case types.ON_REWARDS_PARAMETERS: { state = { ...state } + state.parameters = action.payload.properties + break + } + case types.RECOVER_WALLET: { + let key = action.payload.key + key = key.trim() + + if (!key || key.length === 0) { + let ui = state.ui + ui.walletRecoveryStatus = 0 + + state = { + ...state, + ui + } + + break + } + + chrome.send('brave_rewards.recoverWallet', [key]) + break + } + case types.ON_EXTERNAL_WALLET_PROVIDER_LIST: { + if (!action.payload.list) { + break + } + + state = { ...state } + state.externalWalletProviderList = action.payload.list + break + } + case types.ON_RECOVER_WALLET_DATA: { + state = { ...state } + const result = action.payload.result let ui = state.ui // TODO NZ check why enum can't be used inside Rewards namespace - if (action.payload.properties.status === 1) { - ui.walletServerProblem = true - } else { - state.parameters = action.payload.properties - ui.walletServerProblem = false + ui.walletRecoveryStatus = result + if (result === 0) { + chrome.send('brave_rewards.fetchPromotions') + chrome.send('brave_rewards.fetchBalance') + chrome.send('brave_rewards.getPaymentId') + getCurrentBalanceReport() + ui.modalBackup = false + ui.emptyWallet = false + state.recoveryKey = '' } state = { @@ -96,6 +140,9 @@ const walletReducer: Reducer = (state: Rewards.State, } } else if (status === 1) { // on ledger::type::Result::LEDGER_ERROR ui.walletServerProblem = true + } else if (status === 24) { // on ledger::type::Result::EXPIRED_TOKEN + chrome.send('brave_rewards.getExternalWallet') + state.balance.total = action.payload.balance.total || 0 } state = { @@ -104,6 +151,110 @@ const walletReducer: Reducer = (state: Rewards.State, } break } + case types.GET_EXTERNAL_WALLET: { + chrome.send('brave_rewards.getExternalWallet') + break + } + case types.ON_EXTERNAL_WALLET: { + state = { ...state } + + if (action.payload.result === 24) { // type::Result::EXPIRED_TOKEN + chrome.send('brave_rewards.getExternalWallet') + break + } + + if (action.payload.result === 25) { // type::Result::UPHOLD_BAT_NOT_ALLOWED + state.ui.modalRedirect = 'upholdBATNotAllowedModal' + break + } + + if (action.payload.result === 36) { // type::Result::DEVICE_LIMIT_REACHED + state.ui.modalRedirect = 'deviceLimitReachedModal' + break + } + + if (action.payload.result === 37) { // type::Result::MISMATCHED_PROVIDER_ACCOUNTS + state.ui.modalRedirect = 'mismatchedProviderAccountsModal' + break + } + + if (action.payload.result === 38) { // type::Result::UPHOLD_BLOCKED_USER + state.ui.modalRedirect = 'upholdBlockedUserModal' + break + } + + if (action.payload.result === 39) { // type::Result::UPHOLD_PENDING_USER + state.ui.modalRedirect = 'upholdPendingUserModal' + break + } + + if (action.payload.result === 40) { // type::Result::UPHOLD_RESTRICTED_USER + state.ui.modalRedirect = 'upholdRestrictedUserModal' + break + } + + if (action.payload.result === 0) { // type::Result::LEDGER_OK + chrome.send('brave_rewards.fetchBalance') + } + + state.externalWallet = action.payload.wallet + break + } + case types.GET_MONTHLY_REPORT: { + let month = action.payload.month + let year = action.payload.year + if (month == null) { + month = new Date().getMonth() + 1 + } + + if (year == null) { + year = new Date().getFullYear() + } + + chrome.send('brave_rewards.getMonthlyReport', [month, year]) + break + } + case types.ON_MONTHLY_REPORT: { + state = { ...state } + state.monthlyReport = { + month: action.payload.month, + year: action.payload.year + } + + if (!action.payload.report) { + break + } + + state.monthlyReport = Object.assign(state.monthlyReport, action.payload.report) + break + } + case types.GET_MONTHLY_REPORT_IDS: { + chrome.send('brave_rewards.getMonthlyReportIds') + break + } + case types.ON_MONTHLY_REPORT_IDS: { + state = { ...state } + state.monthlyReportIds = action.payload + break + } + case types.GET_WALLET_PASSPHRASE: { + chrome.send('brave_rewards.getWalletPassphrase') + break + } + case types.ON_WALLET_PASSPHRASE: { + const value = action.payload.passphrase + if (value && value.length > 0) { + state = { ...state } + let ui = state.ui + state.recoveryKey = value + + state = { + ...state, + ui + } + } + break + } } return state diff --git a/components/brave_rewards/resources/android_page/storage.ts b/components/brave_rewards/resources/android_page/storage.ts index a880ef93ffc..862baa592b6 100644 --- a/components/brave_rewards/resources/android_page/storage.ts +++ b/components/brave_rewards/resources/android_page/storage.ts @@ -11,7 +11,7 @@ export const defaultState: Rewards.State = { createdTimestamp: null, enabledAds: true, enabledAdsMigrated: false, - enabledContribute: true, + enabledContribute: false, firstLoad: null, contributionMinTime: 8, contributionMinVisits: 1, diff --git a/components/brave_rewards/resources/android_page/utils.ts b/components/brave_rewards/resources/android_page/utils.tsx similarity index 92% rename from components/brave_rewards/resources/android_page/utils.ts rename to components/brave_rewards/resources/android_page/utils.tsx index ce0602c87ab..9bb9536aada 100644 --- a/components/brave_rewards/resources/android_page/utils.ts +++ b/components/brave_rewards/resources/android_page/utils.tsx @@ -23,10 +23,6 @@ export const convertBalance = (tokens: number, rate: number): string => { return converted.toFixed(2) } -export const getWalletProviderName = (wallet?: Rewards.ExternalWallet) => { - return lookupExternalWalletProviderName(wallet ? wallet.type : '') -} - export const formatConverted = (converted: string, currency: string = 'USD'): string | null => { return `${converted} ${currency}` } @@ -61,11 +57,11 @@ export const constructBackupString = (backupKey: string) => { } export const isPublisherVerified = (status: Rewards.PublisherStatus) => { - return status === 2 + return status > 1 } export const isPublisherConnectedOrVerified = (status: Rewards.PublisherStatus) => { - return status === 2 || status === 1 + return status > 0 } export const isPublisherNotVerified = (status: Rewards.PublisherStatus) => { @@ -78,3 +74,11 @@ export const getCurrentBalanceReport = () => { new Date().getFullYear() ]) } + +export const getWalletProviderName = (wallet?: Rewards.ExternalWallet | string) => { + if (!wallet) { + return '' + } + return lookupExternalWalletProviderName( + typeof wallet === 'string' ? wallet : wallet.type) +} diff --git a/components/brave_rewards/resources/ui/components/modalRedirect/index.tsx b/components/brave_rewards/resources/ui/components/modalRedirect/index.tsx index 2093ff76de1..c922d070ec6 100644 --- a/components/brave_rewards/resources/ui/components/modalRedirect/index.tsx +++ b/components/brave_rewards/resources/ui/components/modalRedirect/index.tsx @@ -25,6 +25,7 @@ export interface Props { learnMore?: string walletType?: string displayCloseButton?: boolean + isMobile?: boolean onClick?: () => void onClose?: () => void } @@ -44,14 +45,28 @@ export default class ModalRedirect extends React.PureComponent { } render () { - const { id, errorText, errorTextLink, titleText, learnMore, displayCloseButton, onClose } = this.props + const { + id, + errorText, + errorTextLink, + titleText, + learnMore, + displayCloseButton, + isMobile, + onClose + } = this.props let errorTextLinkTags = null if (errorText && errorText.includes('$2')) { errorTextLinkTags = splitStringForTag(errorText, 2) } return ( - + {titleText} diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/state/state.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/state/state.cc index fc8e13bb502..c4f346b63c6 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/state/state.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/state/state.cc @@ -155,12 +155,10 @@ void State::GetScoreValues(double* a, double* b) { } void State::SetAutoContributeEnabled(bool enabled) { -#if !defined(OS_ANDROID) // Auto-contribute is not supported for regions where bitFlyer is the external // wallet provider. If AC is not supported, then always set the pref to false. if (ledger_->ledger_client()->GetBooleanOption(option::kIsBitflyerRegion)) enabled = false; -#endif ledger_->database()->SaveEventLog( kAutoContributeEnabled, @@ -173,12 +171,10 @@ void State::SetAutoContributeEnabled(bool enabled) { } bool State::GetAutoContributeEnabled() { -#if !defined(OS_ANDROID) // Auto-contribute is not supported for regions where bitFlyer is the external // wallet provider. If AC is not supported, then always report AC as disabled. if (ledger_->ledger_client()->GetBooleanOption(option::kIsBitflyerRegion)) return false; -#endif return ledger_->ledger_client()->GetBooleanState(kAutoContributeEnabled); } diff --git a/vendor/bat-native-ledger/src/bat/ledger/internal/wallet/wallet.cc b/vendor/bat-native-ledger/src/bat/ledger/internal/wallet/wallet.cc index 832d18cb827..7c1dd1fc749 100644 --- a/vendor/bat-native-ledger/src/bat/ledger/internal/wallet/wallet.cc +++ b/vendor/bat-native-ledger/src/bat/ledger/internal/wallet/wallet.cc @@ -88,7 +88,7 @@ void Wallet::ExternalWalletAuthorization( const std::string& wallet_type, const base::flat_map& args, ledger::ExternalWalletAuthorizationCallback callback) { - ledger_->wallet()->CreateWalletIfNecessary( + CreateWalletIfNecessary( [this, wallet_type, args, callback](const type::Result result) { if (result != type::Result::WALLET_CREATED) { BLOG(0, "Wallet couldn't be created");