diff --git a/android/brave_java_resources.gni b/android/brave_java_resources.gni index bb99f0e511b..784f4ec5de4 100644 --- a/android/brave_java_resources.gni +++ b/android/brave_java_resources.gni @@ -573,6 +573,7 @@ brave_java_resources = [ "java/res/drawable/ic_addresses.xml", "java/res/drawable/ic_appearance.xml", "java/res/drawable/ic_arrow_down.xml", + "java/res/drawable/ic_arrow_down_circular_day_night.xml", "java/res/drawable/ic_arrow_downward.xml", "java/res/drawable/ic_arrow_drop_down_white.xml", "java/res/drawable/ic_arrow_forward.xml", @@ -595,6 +596,7 @@ brave_java_resources = [ "java/res/drawable/ic_calendar.xml", "java/res/drawable/ic_carat_down.xml", "java/res/drawable/ic_card_background.xml", + "java/res/drawable/ic_check.xml", "java/res/drawable/ic_check_circle.xml", "java/res/drawable/ic_checkbox_filled.xml", "java/res/drawable/ic_checkbox_outline.xml", @@ -769,6 +771,7 @@ brave_java_resources = [ "java/res/layout/activity_brave_vpn_support.xml", "java/res/layout/activity_brave_wallet.xml", "java/res/layout/activity_buy_send_swap.xml", + "java/res/layout/activity_network_selector.xml", "java/res/layout/activity_ntp_widget_stack.xml", "java/res/layout/activity_onboarding.xml", "java/res/layout/activity_p3a_onboarding.xml", @@ -883,6 +886,7 @@ brave_java_resources = [ "java/res/layout/fragment_vpn_callout_dialog.xml", "java/res/layout/highlight_layout.xml", "java/res/layout/icon_row_menu_footer.xml", + "java/res/layout/item_network_selector.xml", "java/res/layout/location_status_incognito_badge.xml", "java/res/layout/menu_separator.xml", "java/res/layout/network_spinner_items.xml", diff --git a/android/brave_java_sources.gni b/android/brave_java_sources.gni index ed8fad237c6..48bc531bd0f 100644 --- a/android/brave_java_sources.gni +++ b/android/brave_java_sources.gni @@ -69,10 +69,12 @@ brave_java_sources = [ "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletActivity.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BraveWalletBaseActivity.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/activities/BuySendSwapActivity.java", + "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/activities/NetworkSelectorActivity.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/AccountSpinnerAdapter.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/ApproveTxFragmentPageAdapter.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/CryptoFragmentPageAdapter.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/CryptoWalletOnboardingPagerAdapter.java", + "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/NetworkSelectorAdapter.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/NetworkSpinnerAdapter.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/RecoveryPhraseAdapter.java", "../../brave/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/WalletCoinAdapter.java", diff --git a/android/java/AndroidManifest.xml b/android/java/AndroidManifest.xml index 4e32c12676f..674f55e6cf0 100644 --- a/android/java/AndroidManifest.xml +++ b/android/java/AndroidManifest.xml @@ -85,6 +85,11 @@ android:screenOrientation="sensorPortrait" tools:ignore="LockedOrientationActivity"/> + + startActivity(braveWalletIntent); } + // should only be called if the wallet is setup and unlocked + public void openNetworkSelection() { + Intent braveNetworkSelectionIntent = new Intent(this, NetworkSelectorActivity.class); + braveNetworkSelectionIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + startActivity(braveNetworkSelectionIntent); + } + private void checkForYandexSE() { String countryCode = Locale.getDefault().getCountry(); if (yandexRegions.contains(countryCode)) { diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/activities/NetworkSelectorActivity.java b/android/java/org/chromium/chrome/browser/crypto_wallet/activities/NetworkSelectorActivity.java new file mode 100644 index 00000000000..ae4b72f75f2 --- /dev/null +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/activities/NetworkSelectorActivity.java @@ -0,0 +1,87 @@ +/* Copyright (c) 2022 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.crypto_wallet.activities; + +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.appbar.MaterialToolbar; + +import org.chromium.base.Log; +import org.chromium.brave_wallet.mojom.EthereumChain; +import org.chromium.brave_wallet.mojom.JsonRpcService; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.crypto_wallet.adapters.NetworkSelectorAdapter; +import org.chromium.chrome.browser.crypto_wallet.adapters.NetworkSelectorAdapter.NetworkSelectorItem; +import org.chromium.chrome.browser.crypto_wallet.util.Utils; + +public class NetworkSelectorActivity + extends BraveWalletBaseActivity implements NetworkSelectorAdapter.NetworkClickListener { + private static final String TAG = NetworkSelectorActivity.class.getSimpleName(); + private RecyclerView mRVNetworkSelector; + private NetworkSelectorAdapter networkSelectorAdapter; + private MaterialToolbar mToolbar; + + @Override + protected void triggerLayoutInflation() { + setContentView(R.layout.activity_network_selector); + mToolbar = findViewById(R.id.toolbar); + mToolbar.setTitle(R.string.brave_wallet_network_activity_title); + setSupportActionBar(mToolbar); + + mRVNetworkSelector = findViewById(R.id.rv_network_activity); + onInitialLayoutInflationComplete(); + } + + @Override + public void finishNativeInitialization() { + super.finishNativeInitialization(); + initState(); + } + + private void initState() { + JsonRpcService jsonRpcService = getJsonRpcService(); + assert jsonRpcService != null; + jsonRpcService.getAllNetworks(chains -> { + EthereumChain[] customNetworks = Utils.getCustomNetworks(chains); + networkSelectorAdapter = + new NetworkSelectorAdapter(this, Utils.getNetworksList(this, customNetworks), + Utils.getNetworksAbbrevList(this, customNetworks)); + networkSelectorAdapter.setOnNetworkItemSelected(this); + mRVNetworkSelector.setAdapter(networkSelectorAdapter); + fetchSelectedNetwork(); + }); + } + + private void fetchSelectedNetwork() { + JsonRpcService jsonRpcService = getJsonRpcService(); + assert jsonRpcService != null; + jsonRpcService.getChainId(chainId -> { + jsonRpcService.getAllNetworks(chains -> { + EthereumChain[] customNetworks = Utils.getCustomNetworks(chains); + String strNetwork = Utils.getNetworkText(this, chainId, customNetworks).toString(); + networkSelectorAdapter.setSelectedNetwork(strNetwork); + }); + }); + } + + @Override + public void onNetworkItemSelected(NetworkSelectorItem networkSelectorItem) { + JsonRpcService jsonRpcService = getJsonRpcService(); + if (jsonRpcService != null) { + jsonRpcService.getAllNetworks(chains -> { + EthereumChain[] customNetworks = Utils.getCustomNetworks(chains); + jsonRpcService.setNetwork( + Utils.getNetworkConst( + this, networkSelectorItem.getNetworkName(), customNetworks), + (success) -> { + if (!success) { + Log.e(TAG, "Could not set network"); + } + }); + }); + } + } +} diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/NetworkSelectorAdapter.java b/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/NetworkSelectorAdapter.java new file mode 100644 index 00000000000..45356b29dff --- /dev/null +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/adapters/NetworkSelectorAdapter.java @@ -0,0 +1,160 @@ +/* Copyright (c) 2022 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.crypto_wallet.adapters; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.crypto_wallet.util.Utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class NetworkSelectorAdapter + extends RecyclerView.Adapter { + private Context mContext; + private final ExecutorService mExecutor; + private final Handler mHandler; + private final List networks; + private final LayoutInflater inflater; + private int previousSelectedPos; + private NetworkClickListener networkClickListener; + + public NetworkSelectorAdapter( + Context context, String[] networkNames, String[] networkShortNames) { + assert networkNames.length == networkShortNames.length; + this.mContext = context; + inflater = (LayoutInflater.from(context)); + mExecutor = Executors.newSingleThreadExecutor(); + mHandler = new Handler(Looper.getMainLooper()); + networks = new ArrayList<>(); + init(networkNames, networkShortNames); + } + + @Override + public @NonNull ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + mContext = parent.getContext(); + View view = inflater.inflate(R.layout.item_network_selector, parent, false); + return new ViewHolder(view); + } + + @SuppressLint("NotifyDataSetChanged") + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + final NetworkSelectorItem network = networks.get(position); + + holder.tvName.setText(network.getNetworkShortName()); + Utils.setBlockiesBitmapResource( + mExecutor, mHandler, holder.ivNetworkPicture, network.getNetworkName(), false); + holder.ivSelected.setVisibility(network.isSelected() ? View.VISIBLE : View.GONE); + + holder.itemView.setOnClickListener(v -> { + updateSelectedNetwork(holder.getAdapterPosition()); + if (networkClickListener != null) { + networkClickListener.onNetworkItemSelected(network); + } + }); + } + + @Override + public int getItemCount() { + return networks.size(); + } + + public void setSelectedNetwork(String network) { + for (int i = 0; i < networks.size(); i++) { + NetworkSelectorItem networkSelectorItem = networks.get(i); + if (networkSelectorItem.getNetworkName().equalsIgnoreCase(network)) { + updateSelectedNetwork(i); + break; + } + } + } + + public void setOnNetworkItemSelected(NetworkClickListener networkClickListener) { + this.networkClickListener = networkClickListener; + } + + private void updateSelectedNetwork(int selectedNetworkPosition) { + networks.get(previousSelectedPos).setIsSelected(false); + notifyItemChanged(previousSelectedPos); + + networks.get(selectedNetworkPosition).setIsSelected(true); + previousSelectedPos = selectedNetworkPosition; + notifyItemChanged(selectedNetworkPosition); + } + + private void init(String[] networkNames, String[] networkShortNames) { + for (int i = 0; i < networkNames.length; i++) { + networks.add(new NetworkSelectorItem(networkNames[i], networkShortNames[i])); + } + } + + static class ViewHolder extends RecyclerView.ViewHolder { + ImageView ivNetworkPicture; + TextView tvName; + ImageView ivSelected; + + ViewHolder(View itemView) { + super(itemView); + tvName = itemView.findViewById(R.id.tv_item_network_name); + ivNetworkPicture = itemView.findViewById(R.id.iv_item_network_picture); + ivSelected = itemView.findViewById(R.id.iv_item_network_selector_selected); + } + } + + public static class NetworkSelectorItem { + private String mNetworkName; + private String mNetworkShortName; + private boolean mIsSelected; + + public NetworkSelectorItem(String mNetworkName, String mNetworkShortName) { + this.mNetworkName = mNetworkName; + this.mNetworkShortName = mNetworkShortName; + } + + public String getNetworkName() { + return mNetworkName; + } + + public void setNetworkName(String mNetworkName) { + this.mNetworkName = mNetworkName; + } + + public String getNetworkShortName() { + return mNetworkShortName; + } + + public void setNetworkShortName(String mNetworkShortName) { + this.mNetworkShortName = mNetworkShortName; + } + + public boolean isSelected() { + return mIsSelected; + } + + public void setIsSelected(boolean mIsSelected) { + this.mIsSelected = mIsSelected; + } + } + + public interface NetworkClickListener { + void onNetworkItemSelected(NetworkSelectorItem networkSelectorItem); + } +} diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/PortfolioFragment.java b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/PortfolioFragment.java index 006e2a7eac4..2bb7d3f0234 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/PortfolioFragment.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/fragments/PortfolioFragment.java @@ -42,6 +42,7 @@ import org.chromium.brave_wallet.mojom.KeyringService; import org.chromium.brave_wallet.mojom.TransactionInfo; import org.chromium.brave_wallet.mojom.TxService; import org.chromium.chrome.R; +import org.chromium.chrome.browser.app.BraveActivity; import org.chromium.chrome.browser.crypto_wallet.BlockchainRegistryFactory; import org.chromium.chrome.browser.crypto_wallet.activities.BraveWalletActivity; import org.chromium.chrome.browser.crypto_wallet.adapters.NetworkSpinnerAdapter; @@ -60,17 +61,18 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; -public class PortfolioFragment extends Fragment - implements OnWalletListItemClick, AdapterView.OnItemSelectedListener, ApprovedTxObserver { +public class PortfolioFragment + extends Fragment implements OnWalletListItemClick, ApprovedTxObserver { private static String TAG = "PortfolioFragment"; - private Spinner mSpinner; private TextView mBalance; + private Button mBtnChangeNetwork; private HashMap mPendingTxInfos; private String mFiatSumString; private int mPreviousCheckedRadioId; private int mCurrentTimeframeType; + private String mSelectedChainNetworkName = ""; PortfolioHelper mPortfolioHelper; @@ -130,8 +132,8 @@ public class PortfolioFragment extends Fragment } }); - mSpinner = view.findViewById(R.id.spinner); - mSpinner.setOnItemSelectedListener(this); + mBtnChangeNetwork = view.findViewById(R.id.fragment_portfolio_btn_change_networks); + mBtnChangeNetwork.setOnClickListener(v -> { openNetworkSelection(); }); mBalance = view.findViewById(R.id.balance); mBalance.setOnClickListener(new View.OnClickListener() { @@ -141,18 +143,6 @@ public class PortfolioFragment extends Fragment } }); - // Creating adapter for spinner - JsonRpcService jsonRpcService = getJsonRpcService(); - assert jsonRpcService != null; - jsonRpcService.getAllNetworks(chains -> { - EthereumChain[] customNetworks = Utils.getCustomNetworks(chains); - NetworkSpinnerAdapter dataAdapter = new NetworkSpinnerAdapter(getActivity(), - Utils.getNetworksList(getActivity(), customNetworks), - Utils.getNetworksAbbrevList(getActivity(), customNetworks)); - mSpinner.setAdapter(dataAdapter); - updateNetwork(); - }); - return view; } @@ -162,12 +152,17 @@ public class PortfolioFragment extends Fragment jsonRpcService.getChainId(chain_id -> { jsonRpcService.getAllNetworks(chains -> { EthereumChain[] customNetworks = Utils.getCustomNetworks(chains); - String chainName = mSpinner.getSelectedItem().toString(); - String chainId = Utils.getNetworkConst(getActivity(), chainName, customNetworks); - if (chainId.equals(chain_id)) { + String chainId = Utils.getNetworkConst( + getActivity(), mSelectedChainNetworkName, customNetworks); + if (chainId.equals(chain_id) && !mSelectedChainNetworkName.isEmpty()) { return; } - mSpinner.setSelection(getIndexOf(mSpinner, chain_id, customNetworks)); + mSelectedChainNetworkName = + Utils.getNetworkText(requireActivity(), chain_id, customNetworks) + .toString(); + String strNetworkShort = + Utils.getNetworkShortText(requireActivity(), chain_id).toString(); + updateAccount(strNetworkShort); }); }); } @@ -178,40 +173,6 @@ public class PortfolioFragment extends Fragment updateNetwork(); } - private int getIndexOf(Spinner spinner, String chain_id, EthereumChain[] customNetworks) { - String strNetwork = - Utils.getNetworkText(getActivity(), chain_id, customNetworks).toString(); - for (int i = 0; i < spinner.getCount(); i++) { - if (spinner.getItemAtPosition(i).toString().equalsIgnoreCase(strNetwork)) { - return i; - } - } - - return 0; - } - - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - String item = parent.getItemAtPosition(position).toString(); - JsonRpcService jsonRpcService = getJsonRpcService(); - if (jsonRpcService != null) { - jsonRpcService.getAllNetworks(chains -> { - EthereumChain[] customNetworks = Utils.getCustomNetworks(chains); - jsonRpcService.setNetwork( - Utils.getNetworkConst(getActivity(), item, customNetworks), (success) -> { - if (!success) { - Log.e(TAG, "Could not set network"); - return; - } - updatePortfolioGetPendingTx(true); - }); - }); - } - } - - @Override - public void onNothingSelected(AdapterView arg0) {} - @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); @@ -222,9 +183,9 @@ public class PortfolioFragment extends Fragment JsonRpcService jsonRpcService = getJsonRpcService(); assert jsonRpcService != null; jsonRpcService.getAllNetworks(chains -> { - String chainName = mSpinner.getSelectedItem().toString(); EthereumChain[] customNetworks = Utils.getCustomNetworks(chains); - String chainId = Utils.getNetworkConst(getActivity(), chainName, customNetworks); + String chainId = Utils.getNetworkConst( + getActivity(), mSelectedChainNetworkName, customNetworks); EditVisibleAssetsBottomSheetDialogFragment bottomSheetDialogFragment = EditVisibleAssetsBottomSheetDialogFragment.newInstance( @@ -259,6 +220,11 @@ public class PortfolioFragment extends Fragment }); } + private void updateAccount(String strNetwork) { + mBtnChangeNetwork.setText(strNetwork); + updatePortfolioGetPendingTx(true); + } + private void setUpCoinList(BlockchainToken[] userAssets, HashMap perTokenCryptoSum, HashMap perTokenFiatSum) { View view = getView(); @@ -304,13 +270,19 @@ public class PortfolioFragment extends Fragment assert jsonRpcService != null; jsonRpcService.getAllNetworks(chains -> { EthereumChain[] customNetworks = Utils.getCustomNetworks(chains); - String chainName = mSpinner.getSelectedItem().toString(); - String chainId = Utils.getNetworkConst(getActivity(), chainName, customNetworks); + String chainId = + Utils.getNetworkConst(getActivity(), mSelectedChainNetworkName, customNetworks); Utils.openAssetDetailsActivity(getActivity(), chainId, asset.symbol, asset.name, asset.contractAddress, asset.logo, asset.decimals); }); } + private void openNetworkSelection() { + BraveActivity activity = BraveActivity.getBraveActivity(); + assert activity != null; + activity.openNetworkSelection(); + } + private AssetRatioService getAssetRatioService() { Activity activity = getActivity(); if (activity instanceof BraveWalletActivity) { @@ -410,8 +382,8 @@ public class PortfolioFragment extends Fragment getAssetRatioService(), getJsonRpcService(), accountInfos); } EthereumChain[] customNetworks = Utils.getCustomNetworks(chains); - String chainName = mSpinner.getSelectedItem().toString(); - String chainId = Utils.getNetworkConst(getActivity(), chainName, customNetworks); + String chainId = Utils.getNetworkConst( + getActivity(), mSelectedChainNetworkName, customNetworks); mPortfolioHelper.setChainId(chainId); mPortfolioHelper.calculateBalances(() -> { final String fiatSumString = String.format( diff --git a/android/java/res/drawable/ic_arrow_down_circular_day_night.xml b/android/java/res/drawable/ic_arrow_down_circular_day_night.xml new file mode 100644 index 00000000000..d364dcd928e --- /dev/null +++ b/android/java/res/drawable/ic_arrow_down_circular_day_night.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/java/res/drawable/ic_check.xml b/android/java/res/drawable/ic_check.xml new file mode 100644 index 00000000000..d021a620f0d --- /dev/null +++ b/android/java/res/drawable/ic_check.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/java/res/layout/activity_network_selector.xml b/android/java/res/layout/activity_network_selector.xml new file mode 100644 index 00000000000..33337a904ae --- /dev/null +++ b/android/java/res/layout/activity_network_selector.xml @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/android/java/res/layout/fragment_portfolio.xml b/android/java/res/layout/fragment_portfolio.xml index 04dc01e791f..1e0a438782f 100644 --- a/android/java/res/layout/fragment_portfolio.xml +++ b/android/java/res/layout/fragment_portfolio.xml @@ -1,4 +1,9 @@ + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:layout_marginBottom="16dp" + android:gravity="center" + android:orientation="horizontal"> + android:gravity="center_vertical" + android:text="@string/brave_wallet_portfolio_balance_updating" + android:textColor="@color/wallet_text_color" + android:textStyle="bold" + android:textSize="32sp" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/java/res/layout/item_network_selector.xml b/android/java/res/layout/item_network_selector.xml new file mode 100644 index 00000000000..0d832ba479f --- /dev/null +++ b/android/java/res/layout/item_network_selector.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + diff --git a/android/java/res/values-night/brave_colors.xml b/android/java/res/values-night/brave_colors.xml index d50c2ea5e20..44644b85630 100644 --- a/android/java/res/values-night/brave_colors.xml +++ b/android/java/res/values-night/brave_colors.xml @@ -28,6 +28,10 @@ #212529 + + @android:color/white + @android:color/white + #84889C diff --git a/android/java/res/values/brave_colors.xml b/android/java/res/values/brave_colors.xml index 433b81dca33..4a3ec59586f 100644 --- a/android/java/res/values/brave_colors.xml +++ b/android/java/res/values/brave_colors.xml @@ -21,6 +21,10 @@ #C22700 @color/toolbar_background_primary_dark + + @android:color/black + @android:color/black + #868E96 diff --git a/browser/ui/android/strings/android_brave_strings.grd b/browser/ui/android/strings/android_brave_strings.grd index f2a380b1626..c5808b895f2 100644 --- a/browser/ui/android/strings/android_brave_strings.grd +++ b/browser/ui/android/strings/android_brave_strings.grd @@ -2863,6 +2863,9 @@ If you don't accept this request, VPN will not reconnect and your internet conne Submit + + Select Network + Change amount