From 4c5ed573f5ff7f454e39fcf92c6ce0ed02b25726 Mon Sep 17 00:00:00 2001 From: Deep Date: Tue, 29 Sep 2020 01:49:42 -0400 Subject: [PATCH] Fix an issue for nestedview Update widget UI Update widget stack UI --- android/brave_java_resources.gni | 1 + .../browser/ntp/BraveNewTabPageLayout.java | 163 +++++++++--------- .../browser/ntp/widget/NTPWidgetAdapter.java | 1 - .../NTPWidgetBottomSheetDialogFragment.java | 80 +++++++-- .../ntp/widget/NTPWidgetListAdapter.java | 72 +++++--- .../browser/ntp/widget/NTPWidgetManager.java | 51 ++++++ .../binance/BinanceDepositFragment.java | 81 ++++----- .../binance/BinanceSummaryFragment.java | 51 +++--- .../binance/CryptoWidgetTabAdapter.java | 36 +++- android/java/res/drawable/ic_add.xml | 5 + .../java/res/layout/brave_stats_layout.xml | 1 + .../java/res/layout/crypto_widget_layout.xml | 1 + .../res/layout/fragment_binance_deposit.xml | 16 +- .../res/layout/fragment_binance_summary.xml | 14 +- ...ment_crypto_widget_bottom_sheet_dialog.xml | 1 + ...ragment_ntp_widget_bottom_sheet_dialog.xml | 48 +++--- .../java/res/layout/new_tab_page_layout.xml | 2 +- .../layout/ntp_widget_list_item_layout.xml | 3 +- android/java/res/layout/top_sites_layout.xml | 3 +- .../android/strings/android_brave_strings.grd | 24 +++ 20 files changed, 424 insertions(+), 230 deletions(-) create mode 100644 android/java/res/drawable/ic_add.xml diff --git a/android/brave_java_resources.gni b/android/brave_java_resources.gni index b69fcb5f243..29a26c78392 100644 --- a/android/brave_java_resources.gni +++ b/android/brave_java_resources.gni @@ -558,6 +558,7 @@ brave_java_resources = [ "java/res/drawable-xxxhdpi/verified_disclosure.png", "java/res/drawable-xxxhdpi/wallet_add.png", "java/res/drawable-xxxhdpi/wallet_withdraw.png", + "java/res/drawable/ic_add.xml", "java/res/drawable/bat_panel_gradient.xml", "java/res/drawable/bat_rewards_summary_gradient.xml", "java/res/drawable/blue_rounded_button.xml", diff --git a/android/java/org/chromium/chrome/browser/ntp/BraveNewTabPageLayout.java b/android/java/org/chromium/chrome/browser/ntp/BraveNewTabPageLayout.java index 1e3283435ea..70d4c1f9eea 100644 --- a/android/java/org/chromium/chrome/browser/ntp/BraveNewTabPageLayout.java +++ b/android/java/org/chromium/chrome/browser/ntp/BraveNewTabPageLayout.java @@ -163,6 +163,10 @@ public class BraveNewTabPageLayout extends NewTabPageLayout { @Override public void onPageSelected(int position) { + cancelTimer(); + if (NTPWidgetManager.getInstance().getBinanceWidget() == position) { + startTimer(); + } updateAndShowIndicators(position); NTPWidgetManager.getInstance().setNTPWidgetOrder(position); } @@ -178,82 +182,70 @@ public class BraveNewTabPageLayout extends NewTabPageLayout { LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); Map ntpWidgetMap = new TreeMap<>(); - if (ntpWidgetManager.getPrivateStatsWidget() != -1) { - View mBraveStatsView = inflater.inflate(R.layout.brave_stats_layout, null); - mBraveStatsView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - checkForBraveStats(); - } - }); - NTPWidgetItem ntpWidgetItem = new NTPWidgetItem(NTPWidgetManager.PREF_PRIVATE_STATS, - "Privacy Stats", - "Trackers & Ads Blocked, Saved Bandwidth, and Time Saved Estimates."); - ntpWidgetItem.setWidgetView(mBraveStatsView); - ntpWidgetMap.put(ntpWidgetManager.getPrivateStatsWidget(), ntpWidgetItem); - } - if (ntpWidgetManager.getFavoritesWidget() != -1) { - View mTopSitesLayout = inflater.inflate(R.layout.top_sites_layout, null); - FrameLayout mTopSitesGridLayout = mTopSitesLayout.findViewById(R.id.top_sites_grid_layout); - NTPWidgetItem ntpWidgetItem = new NTPWidgetItem(NTPWidgetManager.PREF_FAVORITES, - "Favorites", - "Trackers & Ads Blocked, Saved Bandwidth, and Time Saved Estimates."); - if (shouldShowSuperReferral() && superReferralSitesLayout != null) { - mTopSitesGridLayout.addView(superReferralSitesLayout); - ntpWidgetItem.setWidgetView(mTopSitesLayout); - ntpWidgetMap.put(ntpWidgetManager.getFavoritesWidget(), ntpWidgetItem); - } else if (!mNTPBackgroundImagesBridge.isSuperReferral() - || !NTPBackgroundImagesBridge.enableSponsoredImages() - || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - boolean showPlaceholder = getTileGroup().hasReceivedData() && getTileGroup().isEmpty(); - if (mSiteSectionView != null - && !showPlaceholder) { - if (mSiteSectionView.getParent() != null) { - ((ViewGroup)mSiteSectionView.getParent()).removeView(mSiteSectionView); // <- fix + for (String widget : ntpWidgetManager.getUsedWidgets()) { + NTPWidgetItem ntpWidgetItem = NTPWidgetManager.mWidgetsMap.get(widget); + if (widget.equals(NTPWidgetManager.PREF_PRIVATE_STATS)) { + View mBraveStatsView = inflater.inflate(R.layout.brave_stats_layout, null); + mBraveStatsView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + checkForBraveStats(); } - mTopSitesGridLayout.addView(mSiteSectionView); + }); + ntpWidgetItem.setWidgetView(mBraveStatsView); + ntpWidgetMap.put(ntpWidgetManager.getPrivateStatsWidget(), ntpWidgetItem); + } else if (widget.equals(NTPWidgetManager.PREF_FAVORITES)) { + View mTopSitesLayout = inflater.inflate(R.layout.top_sites_layout, null); + FrameLayout mTopSitesGridLayout = mTopSitesLayout.findViewById(R.id.top_sites_grid_layout); + + if (shouldShowSuperReferral() && superReferralSitesLayout != null) { + if (superReferralSitesLayout.getParent() != null) { + ((ViewGroup)superReferralSitesLayout.getParent()).removeView(superReferralSitesLayout); // <- fix + } + mTopSitesGridLayout.addView(superReferralSitesLayout); ntpWidgetItem.setWidgetView(mTopSitesLayout); ntpWidgetMap.put(ntpWidgetManager.getFavoritesWidget(), ntpWidgetItem); - } - } - } - // if (ntpWidgetManager.getBraveRewardsWidget() != -1) { - // View braveRewardsWidgetView = - // inflater.inflate(R.layout.brave_rewards_widget_layout, null); - // NTPWidgetItem ntpWidgetItem = new NTPWidgetItem(NTPWidgetManager.PREF_BRAVE_REWARDS, - // "Brave Rewards", - // "Trackers & Ads Blocked, Saved Bandwidth, and Time Saved Estimates."); - // ntpWidgetItem.setWidgetView(braveRewardsWidgetView); - // ntpWidgetMap.put(ntpWidgetManager.getBraveRewardsWidget(), ntpWidgetItem); - // } - if (ntpWidgetManager.getBinanceWidget() != -1) { - View binanceWidgetView = inflater.inflate(R.layout.crypto_widget_layout, null); - binanceWidgetView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (BinanceWidgetManager.getInstance().isUserAuthenticatedForBinance()) { - CryptoWidgetBottomSheetDialogFragment cryptoWidgetBottomSheetDialogFragment = - new CryptoWidgetBottomSheetDialogFragment(); - cryptoWidgetBottomSheetDialogFragment.show( - ((BraveActivity) mActivity).getSupportFragmentManager(), - CryptoWidgetBottomSheetDialogFragment.TAG_FRAGMENT); + } else if (!mNTPBackgroundImagesBridge.isSuperReferral() + || !NTPBackgroundImagesBridge.enableSponsoredImages() + || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + boolean showPlaceholder = getTileGroup().hasReceivedData() && getTileGroup().isEmpty(); + if (mSiteSectionView != null + && !showPlaceholder) { + if (mSiteSectionView.getParent() != null) { + ((ViewGroup)mSiteSectionView.getParent()).removeView(mSiteSectionView); // <- fix + } + mTopSitesGridLayout.addView(mSiteSectionView); + ntpWidgetItem.setWidgetView(mTopSitesLayout); + ntpWidgetMap.put(ntpWidgetManager.getFavoritesWidget(), ntpWidgetItem); } } - }); - Button connectButton = binanceWidgetView.findViewById(R.id.btn_connect); - connectButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Log.e("NTP", "Binance URL : " + mBinanceNativeWorker.getOAuthClientUrl()); - TabUtils.openUrlInSameTab(mBinanceNativeWorker.getOAuthClientUrl()); - } - }); - NTPWidgetItem ntpWidgetItem = new NTPWidgetItem(NTPWidgetManager.PREF_BINANCE, - "Binance", - "Trackers & Ads Blocked, Saved Bandwidth, and Time Saved Estimates."); - ntpWidgetItem.setWidgetView(binanceWidgetView); - ntpWidgetMap.put(ntpWidgetManager.getBinanceWidget(), ntpWidgetItem); + } else if (widget.equals(NTPWidgetManager.PREF_BINANCE)) { + View binanceWidgetView = inflater.inflate(R.layout.crypto_widget_layout, null); + binanceWidgetView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (BinanceWidgetManager.getInstance().isUserAuthenticatedForBinance()) { + cancelTimer(); + CryptoWidgetBottomSheetDialogFragment cryptoWidgetBottomSheetDialogFragment = + new CryptoWidgetBottomSheetDialogFragment(); + cryptoWidgetBottomSheetDialogFragment.show( + ((BraveActivity) mActivity).getSupportFragmentManager(), + CryptoWidgetBottomSheetDialogFragment.TAG_FRAGMENT); + } + } + }); + Button connectButton = binanceWidgetView.findViewById(R.id.btn_connect); + connectButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Log.e("NTP", "Binance URL : " + mBinanceNativeWorker.getOAuthClientUrl()); + TabUtils.openUrlInSameTab(mBinanceNativeWorker.getOAuthClientUrl()); + } + }); + ntpWidgetItem.setWidgetView(binanceWidgetView); + ntpWidgetMap.put(ntpWidgetManager.getBinanceWidget(), ntpWidgetItem); + } } widgetList = new ArrayList(ntpWidgetMap.values()); @@ -268,15 +260,16 @@ public class BraveNewTabPageLayout extends NewTabPageLayout { private void showWidgetBasedOnOrder() { if (ntpWidgetViewPager != null) { int selectedOrder = NTPWidgetManager.getInstance().getNTPWidgetOrder(); - ntpWidgetViewPager.setCurrentItem(selectedOrder); + // ntpWidgetViewPager.setCurrentItem(selectedOrder); updateAndShowIndicators(selectedOrder); } } private void showWidgets() { if (ntpWidgetAdapter != null) { - ntpWidgetAdapter.clearWidgets(); - ntpWidgetAdapter.setWidgetList(widgetList); + setWidgetList(); + List tempList = widgetList; + ntpWidgetAdapter.setWidgetList(tempList); ntpWidgetAdapter.notifyDataSetChanged(); showWidgetBasedOnOrder(); } @@ -307,12 +300,13 @@ public class BraveNewTabPageLayout extends NewTabPageLayout { } protected int getMaxRowsForMostVisitedTiles() { - if (UserPrefs.get(Profile.getLastUsedRegularProfile()).getBoolean(BravePref.NEW_TAB_PAGE_SHOW_BACKGROUND_IMAGE) - && NTPUtil.shouldEnableNTPFeature()) { - return 1; - } else { - return 2; - } + // if (UserPrefs.get(Profile.getLastUsedRegularProfile()).getBoolean(BravePref.NEW_TAB_PAGE_SHOW_BACKGROUND_IMAGE) + // && NTPUtil.shouldEnableNTPFeature()) { + // return 1; + // } else { + // return 2; + // } + return 1; } @Override @@ -339,7 +333,6 @@ public class BraveNewTabPageLayout extends NewTabPageLayout { && !OnboardingPrefManager.getInstance().shouldShowBadgeAnimation()) { mBadgeAnimationView.setVisibility(View.INVISIBLE); } - setWidgetList(); showWidgets(); if (BinanceWidgetManager.getInstance().isUserAuthenticatedForBinance()) { mBinanceNativeWorker.getAccountBalances(); @@ -712,10 +705,11 @@ public class BraveNewTabPageLayout extends NewTabPageLayout { new NTPWidgetAdapter.NTPWidgetListener() { @Override public void onMenuEdit() { + cancelTimer(); NTPWidgetBottomSheetDialogFragment ntpWidgetBottomSheetDialogFragment = NTPWidgetBottomSheetDialogFragment.newInstance(); ntpWidgetBottomSheetDialogFragment.setNTPWidgetListener(ntpWidgetListener); - ntpWidgetBottomSheetDialogFragment.setWidgetList(widgetList); + // ntpWidgetBottomSheetDialogFragment.setWidgetList(widgetList); ntpWidgetBottomSheetDialogFragment.show( ((BraveActivity) mActivity).getSupportFragmentManager(), "NTPWidgetBottomSheetDialogFragment"); @@ -745,8 +739,11 @@ public class BraveNewTabPageLayout extends NewTabPageLayout { @Override public void onBottomSheetDismiss() { - // showWidgets(); - ntpWidgetAdapter.notifyDataSetChanged(); + showWidgets(); + cancelTimer(); + if (ntpWidgetViewPager.getCurrentItem() == NTPWidgetManager.getInstance().getBinanceWidget()) { + startTimer(); + } } }; diff --git a/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetAdapter.java b/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetAdapter.java index ab1094b593f..2cf542c3005 100644 --- a/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetAdapter.java +++ b/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetAdapter.java @@ -88,7 +88,6 @@ public class NTPWidgetAdapter extends PagerAdapter { updateBraveStats(mainView); } else if (ntpWidgetItem.getWidgetType().equals(NTPWidgetManager.PREF_BINANCE)) { Button connectButton = mainView.findViewById(R.id.btn_connect); - // connectButton.setOnClickListener(null); LinearLayout binanceWidgetLayout = mainView.findViewById(R.id.binance_widget_layout); TextView binanceBalanceText = binanceWidgetLayout.findViewById(R.id.binance_balance_text); TextView binanceUSDBalanceText = binanceWidgetLayout.findViewById(R.id.binance_usd_balance_text); diff --git a/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetBottomSheetDialogFragment.java b/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetBottomSheetDialogFragment.java index 6cc538da895..fbc5a875745 100644 --- a/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetBottomSheetDialogFragment.java +++ b/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetBottomSheetDialogFragment.java @@ -10,6 +10,7 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.LinearLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -29,8 +30,17 @@ import java.util.List; public class NTPWidgetBottomSheetDialogFragment extends BottomSheetDialogFragment { private NTPWidgetAdapter.NTPWidgetListener ntpWidgetListener; - private NTPWidgetListAdapter ntpWidgetListAdapter; - private List widgetList = new ArrayList(); + private RecyclerView usedWidgetsRecyclerView; + private RecyclerView availableWidgetsRecyclerView; + private NTPWidgetListAdapter usedNtpWidgetListAdapter; + private NTPWidgetListAdapter availableNtpWidgetListAdapter; + private LinearLayout availableWidgetLayout; + public static final int USED_WIDGET = 0; + public static final int AVAILABLE_WIDGET = 1; + + public interface NTPWidgetStackUpdateListener { + void onWidgetStackUpdate(); + } public void setNTPWidgetListener(NTPWidgetAdapter.NTPWidgetListener ntpWidgetListener) { this.ntpWidgetListener = ntpWidgetListener; @@ -40,39 +50,77 @@ public class NTPWidgetBottomSheetDialogFragment extends BottomSheetDialogFragmen return new NTPWidgetBottomSheetDialogFragment(); } - public void setWidgetList(List widgetList) { - this.widgetList = widgetList; - } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_ntp_widget_bottom_sheet_dialog, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - RecyclerView usedWidgetsRecyclerView = view.findViewById(R.id.used_widget_list); + + List usedWidgetList = NTPWidgetManager.getInstance().getUsedWidgets(); + List availableWidgetList = NTPWidgetManager.getInstance().getAvailableWidgets(); + + usedWidgetsRecyclerView = view.findViewById(R.id.used_widget_list); usedWidgetsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - ntpWidgetListAdapter = new NTPWidgetListAdapter(); - SwipeAndDragHelper swipeAndDragHelper = new SwipeAndDragHelper(ntpWidgetListAdapter); + usedNtpWidgetListAdapter = new NTPWidgetListAdapter(); + SwipeAndDragHelper swipeAndDragHelper = new SwipeAndDragHelper(usedNtpWidgetListAdapter); ItemTouchHelper touchHelper = new ItemTouchHelper(swipeAndDragHelper); - ntpWidgetListAdapter.setTouchHelper(touchHelper); - ntpWidgetListAdapter.setNTPWidgetListener(ntpWidgetListener); - usedWidgetsRecyclerView.setAdapter(ntpWidgetListAdapter); + usedNtpWidgetListAdapter.setTouchHelper(touchHelper); + usedNtpWidgetListAdapter.setNTPWidgetListener(ntpWidgetListener); + usedNtpWidgetListAdapter.setNTPWidgetStackUpdateListener(ntpWidgetStackUpdateListener); + usedNtpWidgetListAdapter.setNTPWidgetType(USED_WIDGET); + usedWidgetsRecyclerView.setAdapter(usedNtpWidgetListAdapter); touchHelper.attachToRecyclerView(usedWidgetsRecyclerView); - ntpWidgetListAdapter.setWidgetList(widgetList); + usedNtpWidgetListAdapter.setWidgetList(usedWidgetList); + + availableWidgetLayout = view.findViewById(R.id.available_widget_layout); + + availableWidgetsRecyclerView = view.findViewById(R.id.available_widget_list); + availableWidgetsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + availableNtpWidgetListAdapter = new NTPWidgetListAdapter(); + availableNtpWidgetListAdapter.setNTPWidgetListener(ntpWidgetListener); + availableNtpWidgetListAdapter.setNTPWidgetStackUpdateListener(ntpWidgetStackUpdateListener); + availableNtpWidgetListAdapter.setNTPWidgetType(AVAILABLE_WIDGET); + availableWidgetsRecyclerView.setAdapter(availableNtpWidgetListAdapter); + availableNtpWidgetListAdapter.setWidgetList(availableWidgetList); + if (availableWidgetList.size() > 0) { + availableWidgetLayout.setVisibility(View.VISIBLE); + } else { + availableWidgetLayout.setVisibility(View.GONE); + } } @Override public void onDismiss(@NonNull DialogInterface dialog) { super.onDismiss(dialog); - for (int i = 0; i < ntpWidgetListAdapter.getWidgetList().size(); i++) { + for (int i = 0; i < usedNtpWidgetListAdapter.getWidgetList().size(); i++) { NTPWidgetManager.getInstance().setWidget( - ntpWidgetListAdapter.getWidgetList().get(i).getWidgetType(), i); + usedNtpWidgetListAdapter.getWidgetList().get(i), i); } ntpWidgetListener.onBottomSheetDismiss(); } + + private NTPWidgetStackUpdateListener ntpWidgetStackUpdateListener = + new NTPWidgetStackUpdateListener() { + @Override + public void onWidgetStackUpdate() { + List usedWidgetList = NTPWidgetManager.getInstance().getUsedWidgets(); + List availableWidgetList = NTPWidgetManager.getInstance().getAvailableWidgets(); + + usedNtpWidgetListAdapter.setWidgetList(usedWidgetList); + usedNtpWidgetListAdapter.notifyDataSetChanged(); + + if (availableWidgetList.size() > 0) { + availableWidgetLayout.setVisibility(View.VISIBLE); + availableNtpWidgetListAdapter.setWidgetList(availableWidgetList); + availableNtpWidgetListAdapter.notifyDataSetChanged(); + } else { + availableWidgetLayout.setVisibility(View.GONE); + } + } + }; } diff --git a/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetListAdapter.java b/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetListAdapter.java index 6060412ab11..9c1c13ef277 100644 --- a/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetListAdapter.java +++ b/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetListAdapter.java @@ -25,21 +25,30 @@ import org.chromium.chrome.browser.ntp.widget.SwipeAndDragHelper; import java.util.List; public class NTPWidgetListAdapter extends RecyclerView.Adapter - implements SwipeAndDragHelper.ActionCompletionContract { - private List widgetList; + implements SwipeAndDragHelper.ActionCompletionContract { + private List widgetList; private ItemTouchHelper touchHelper; - private NTPWidgetAdapter.NTPWidgetListener ntpWidgetListener; + private NTPWidgetBottomSheetDialogFragment.NTPWidgetStackUpdateListener ntpWidgetStackUpdateListener; + private int ntpWidgetType; public void setNTPWidgetListener(NTPWidgetAdapter.NTPWidgetListener ntpWidgetListener) { this.ntpWidgetListener = ntpWidgetListener; } + public void setNTPWidgetStackUpdateListener(NTPWidgetBottomSheetDialogFragment.NTPWidgetStackUpdateListener ntpWidgetStackUpdateListener) { + this.ntpWidgetStackUpdateListener = ntpWidgetStackUpdateListener; + } + + public void setNTPWidgetType(int ntpWidgetType) { + this.ntpWidgetType = ntpWidgetType; + } + @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.ntp_widget_list_item_layout, parent, false); + .inflate(R.layout.ntp_widget_list_item_layout, parent, false); return new NTPWidgetViewHolder(view); } @@ -47,17 +56,32 @@ public class NTPWidgetListAdapter extends RecyclerView.Adapter widgetList) { + public void setWidgetList(List widgetList) { this.widgetList = widgetList; - notifyDataSetChanged(); } - public List getWidgetList() { + public List getWidgetList() { return this.widgetList; } + public void clearWidgetList() { + this.widgetList.clear(); + } + @Override public void onViewMoved(int oldPosition, int newPosition) { - NTPWidgetItem targetNTPWidgetItem = widgetList.get(oldPosition); - NTPWidgetItem ntpWidgetItem = new NTPWidgetItem(targetNTPWidgetItem); + String targetWidget = widgetList.get(oldPosition); + String newWidget = targetWidget; widgetList.remove(oldPosition); - widgetList.add(newPosition, ntpWidgetItem); + widgetList.add(newPosition, newWidget); notifyItemMoved(oldPosition, newPosition); } @Override public void onViewSwiped(int position) { - NTPWidgetItem ntpWidgetItem = widgetList.get(position); - NTPWidgetManager.getInstance().setWidget(ntpWidgetItem.getWidgetType(), -1); + String widget = widgetList.get(position); + NTPWidgetManager.getInstance().setWidget(widget, -1); widgetList.remove(position); notifyItemRemoved(position); + ntpWidgetStackUpdateListener.onWidgetStackUpdate(); } void setTouchHelper(ItemTouchHelper touchHelper) { diff --git a/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetManager.java b/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetManager.java index 66cbdf89268..051d44b092b 100644 --- a/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetManager.java +++ b/android/java/org/chromium/chrome/browser/ntp/widget/NTPWidgetManager.java @@ -8,14 +8,19 @@ package org.chromium.chrome.browser.ntp.widget; import android.content.SharedPreferences; +import android.content.Context; +import org.chromium.chrome.R; import org.chromium.base.ContextUtils; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.HashMap; import java.util.TreeMap; +import org.chromium.chrome.browser.ntp.widget.NTPWidgetItem; + public class NTPWidgetManager { public static final String PREF_PRIVATE_STATS = "private_stats"; public static final String PREF_FAVORITES = "favorites"; @@ -26,6 +31,24 @@ public class NTPWidgetManager { private static NTPWidgetManager sInstance; private final SharedPreferences mSharedPreferences; + private static Context mContext = ContextUtils.getApplicationContext(); + + public static Map mWidgetsMap = new HashMap() { + { + put(PREF_PRIVATE_STATS, + new NTPWidgetItem(PREF_PRIVATE_STATS, + mContext.getResources().getString(R.string.privacy_stats), + mContext.getResources().getString(R.string.privacy_stats_text))); + put(PREF_FAVORITES, + new NTPWidgetItem(PREF_FAVORITES, + mContext.getResources().getString(R.string.favorites), + mContext.getResources().getString(R.string.privacy_stats_text))); + put(PREF_BINANCE, + new NTPWidgetItem(PREF_BINANCE, + mContext.getResources().getString(R.string.binance), + mContext.getResources().getString(R.string.privacy_stats_text))); + } + }; private NTPWidgetManager() { mSharedPreferences = ContextUtils.getAppSharedPreferences(); @@ -69,4 +92,32 @@ public class NTPWidgetManager { sharedPreferencesEditor.putInt(PREF_NTP_WIDGET_ORDER, position); sharedPreferencesEditor.apply(); } + + public List getUsedWidgets() { + Map usedWidgetMap = new TreeMap<>(); + if (getPrivateStatsWidget() != -1) { + usedWidgetMap.put(getPrivateStatsWidget(), PREF_PRIVATE_STATS); + } + if (getFavoritesWidget() != -1) { + usedWidgetMap.put(getFavoritesWidget(), PREF_FAVORITES); + } + if (getBinanceWidget() != -1) { + usedWidgetMap.put(getBinanceWidget(), PREF_BINANCE); + } + return new ArrayList(usedWidgetMap.values()); + } + + public List getAvailableWidgets() { + List availableWidgets = new ArrayList<>(); + if (getPrivateStatsWidget() == -1) { + availableWidgets.add(PREF_PRIVATE_STATS); + } + if (getFavoritesWidget() == -1) { + availableWidgets.add(PREF_FAVORITES); + } + if (getBinanceWidget() == -1) { + availableWidgets.add(PREF_BINANCE); + } + return availableWidgets; + } } \ No newline at end of file diff --git a/android/java/org/chromium/chrome/browser/widget/crypto/binance/BinanceDepositFragment.java b/android/java/org/chromium/chrome/browser/widget/crypto/binance/BinanceDepositFragment.java index 3b86a4846e4..c6fa60961ae 100644 --- a/android/java/org/chromium/chrome/browser/widget/crypto/binance/BinanceDepositFragment.java +++ b/android/java/org/chromium/chrome/browser/widget/crypto/binance/BinanceDepositFragment.java @@ -14,10 +14,12 @@ import android.widget.TextView; import android.widget.Button; import android.widget.ImageView; import android.widget.FrameLayout; +import android.widget.LinearLayout; import android.view.MotionEvent; import android.text.TextUtils; import androidx.fragment.app.Fragment; +import androidx.core.widget.NestedScrollView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -45,11 +47,10 @@ import org.chromium.chrome.R; */ public class BinanceDepositFragment extends Fragment { private BinanceNativeWorker mBinanceNativeWorker; - private BinanceDepositAdapter mBinanceDepositAdapter; - - private RecyclerView currencyRecyclerView; private CoinNetworkModel selectedCoinNetworkModel; + private LinearLayout depositCoinListLayout; + private NestedScrollView currentNestedScrollView; public BinanceDepositFragment() { // Required empty public constructor @@ -78,42 +79,8 @@ public class BinanceDepositFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - currencyRecyclerView = view.findViewById(R.id.recyclerview_currency_list); - currencyRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - currencyRecyclerView.setOnFlingListener(new RecyclerView.OnFlingListener() { - @Override - public boolean onFling(int velocityX, int velocityY) { - currencyRecyclerView.dispatchNestedFling(velocityX, velocityY, false); - return false; - } - }); - currencyRecyclerView.setOnTouchListener(new RecyclerView.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - int action = event.getAction(); - switch (action) { - case MotionEvent.ACTION_DOWN: - // Disallow NestedScrollView to intercept touch events. - v.getParent().requestDisallowInterceptTouchEvent(true); - break; - - case MotionEvent.ACTION_UP: - // Allow NestedScrollView to intercept touch events. - v.getParent().requestDisallowInterceptTouchEvent(false); - break; - } - - // Handle RecyclerView touch events. - v.onTouchEvent(event); - return true; - } - }); - mBinanceDepositAdapter = new BinanceDepositAdapter(); - currencyRecyclerView.setAdapter(mBinanceDepositAdapter); - mBinanceDepositAdapter.setBinanceDepositListener(binanceDepositListener); - + depositCoinListLayout = view.findViewById(R.id.deposit_layout); mBinanceNativeWorker.getCoinNetworks(); - // Log.e("NTP", "Set CoinNetworks"); } private BinanceDepositAdapter.BinanceDepositListener binanceDepositListener = @@ -130,20 +97,35 @@ public class BinanceDepositFragment extends Fragment { public void OnGetAccessToken(boolean isSuccess) {}; @Override - public void OnGetAccountBalances(String jsonBalances, boolean isSuccess) { - // Log.e("NTP", "AccountBalances : " + jsonBalances); - }; + public void OnGetAccountBalances(String jsonBalances, boolean isSuccess) {}; @Override public void OnGetConvertQuote(String quoteId, String quotePrice, String totalFee, String totalAmount) {}; @Override public void OnGetCoinNetworks(String jsonNetworks) { - // Log.e("NTP", "OnGetCoinNetworks"+jsonNetworks); try { BinanceCoinNetworks binanceCoinNetworks = new BinanceCoinNetworks(jsonNetworks); - mBinanceDepositAdapter.setCurrencyList(binanceCoinNetworks.getCoinNetworksList()); - // Log.e("NTP", "CoinNetworks : " + binanceCoinNetworks.toString()); + LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + for (CoinNetworkModel coinNetworkModel : binanceCoinNetworks.getCoinNetworksList()) { + final View view = inflater.inflate(R.layout.binance_deposit_item, null); + + ImageView currencyImageView = view.findViewById(R.id.currency_image); + TextView currencyText = view.findViewById(R.id.currency_text); + + currencyText.setText(coinNetworkModel.getCoin() + (TextUtils.isEmpty(coinNetworkModel.getCoinDesc()) ? "" : " (" + coinNetworkModel.getCoinDesc() + ")")); + currencyImageView.setImageResource(coinNetworkModel.getCoinRes()); + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + selectedCoinNetworkModel = coinNetworkModel; + mBinanceNativeWorker.getDepositInfo(coinNetworkModel.getCoin(), coinNetworkModel.getTickerNetwork()); + } + }); + if (depositCoinListLayout != null) { + depositCoinListLayout.addView(view); + } + } } catch (JSONException e) { Log.e("NTP", e.getMessage()); } @@ -188,8 +170,8 @@ public class BinanceDepositFragment extends Fragment { depositBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - if (currencyRecyclerView != null) { - currencyRecyclerView.setVisibility(View.VISIBLE); + if (depositCoinListLayout != null) { + depositCoinListLayout.setVisibility(View.VISIBLE); depositLayout.setVisibility(View.GONE); currencyMemoText.setVisibility(View.GONE); currencyMemoValueText.setVisibility(View.GONE); @@ -199,8 +181,8 @@ public class BinanceDepositFragment extends Fragment { } }); depositLayout.setVisibility(View.VISIBLE); - if (currencyRecyclerView != null) { - currencyRecyclerView.setVisibility(View.GONE); + if (depositCoinListLayout != null) { + depositCoinListLayout.setVisibility(View.GONE); } currencyAddressValueText.setText(depositAddress); @@ -228,9 +210,6 @@ public class BinanceDepositFragment extends Fragment { } } }); - - Log.e("NTP", "depositAddress : " + depositAddress); - Log.e("NTP", "depositeTag : " + depositTag); } }; diff --git a/android/java/org/chromium/chrome/browser/widget/crypto/binance/BinanceSummaryFragment.java b/android/java/org/chromium/chrome/browser/widget/crypto/binance/BinanceSummaryFragment.java index cdd4d2d4672..ea95b7af17b 100644 --- a/android/java/org/chromium/chrome/browser/widget/crypto/binance/BinanceSummaryFragment.java +++ b/android/java/org/chromium/chrome/browser/widget/crypto/binance/BinanceSummaryFragment.java @@ -6,10 +6,13 @@ package org.chromium.chrome.browser.widget.crypto.binance; import android.os.Bundle; +import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.util.Pair; import androidx.fragment.app.Fragment; @@ -38,6 +41,8 @@ import org.chromium.chrome.R; public class BinanceSummaryFragment extends Fragment { private BinanceNativeWorker mBinanceNativeWorker; private CurrencyListAdapter mCurrencyListAdapter; + private LinearLayout summaryLayout; + private NestedScrollView currentNestedScrollView; public BinanceSummaryFragment() { // Required empty public constructor @@ -49,16 +54,6 @@ public class BinanceSummaryFragment extends Fragment { mBinanceNativeWorker = BinanceNativeWorker.getInstance(); } - // @Override - // public void setUserVisibleHint(boolean isVisibleToUser) { - // super.setUserVisibleHint(isVisibleToUser); - // if (isVisibleToUser && isResumed()) { - // mBinanceNativeWorker.AddObserver(mBinanaceObserver); - // } else { - // mBinanceNativeWorker.RemoveObserver(mBinanaceObserver); - // } - // } - @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -76,11 +71,6 @@ public class BinanceSummaryFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - RecyclerView currencyRecyclerView = view.findViewById(R.id.recyclerview_currency_list); - currencyRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - mCurrencyListAdapter = new CurrencyListAdapter(); - currencyRecyclerView.setAdapter(mCurrencyListAdapter); - TextView binanceBalanceText = view.findViewById(R.id.binance_balance_text); TextView binanceUSDBalanceText = view.findViewById(R.id.binance_usd_balance_text); BinanceAccountBalance binanceAccountBalance = BinanceWidgetManager.getInstance().getBinanceAccountBalance(); @@ -88,9 +78,8 @@ public class BinanceSummaryFragment extends Fragment { binanceBalanceText.setText(String.format(getActivity().getResources().getString(R.string.btc_balance), String.valueOf(binanceAccountBalance.getTotalBTC()))); binanceUSDBalanceText.setText(String.format(getActivity().getResources().getString(R.string.usd_balance), String.valueOf(binanceAccountBalance.getTotalUSD()))); } - + summaryLayout = view.findViewById(R.id.summary_layout); mBinanceNativeWorker.getCoinNetworks(); - // Log.e("NTP", "Set CoinNetworks"); } private BinanceObserver mBinanaceObserver = new BinanceObserver() { @@ -98,20 +87,36 @@ public class BinanceSummaryFragment extends Fragment { public void OnGetAccessToken(boolean isSuccess) {}; @Override - public void OnGetAccountBalances(String jsonBalances, boolean isSuccess) { - // Log.e("NTP", "AccountBalances : " + jsonBalances); - }; + public void OnGetAccountBalances(String jsonBalances, boolean isSuccess) {}; @Override public void OnGetConvertQuote(String quoteId, String quotePrice, String totalFee, String totalAmount) {}; @Override public void OnGetCoinNetworks(String jsonNetworks) { - // Log.e("NTP", "OnGetCoinNetworks"+jsonNetworks); try { BinanceCoinNetworks binanceCoinNetworks = new BinanceCoinNetworks(jsonNetworks); - mCurrencyListAdapter.setCurrencyList(binanceCoinNetworks.getCoinNetworksList()); - // Log.e("NTP", "CoinNetworks : " + binanceCoinNetworks.toString()); + LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + for (CoinNetworkModel coinNetworkModel : binanceCoinNetworks.getCoinNetworksList()) { + final View view = inflater.inflate(R.layout.binance_currency_item, null); + + ImageView currencyImageView = view.findViewById(R.id.currency_image); + TextView currencyText = view.findViewById(R.id.currency_text); + TextView currencyValueText = view.findViewById(R.id.currency_value_text); + TextView currencyUsdText = view.findViewById(R.id.currency_usd_text); + + currencyText.setText(coinNetworkModel.getCoin()); + currencyImageView.setImageResource(coinNetworkModel.getCoinRes()); + BinanceAccountBalance binanceAccountBalance = BinanceWidgetManager.getInstance().getBinanceAccountBalance(); + if (binanceAccountBalance.getCurrencyValue(coinNetworkModel.getCoin()) != null) { + Pair currencyValue = binanceAccountBalance.getCurrencyValue(coinNetworkModel.getCoin()); + currencyValueText.setText(String.valueOf(currencyValue.first)); + currencyUsdText.setText(String.format(getActivity().getResources().getString(R.string.usd_balance), String.valueOf(currencyValue.second))); + } + if (summaryLayout != null) { + summaryLayout.addView(view); + } + } } catch (JSONException e) { Log.e("NTP", e.getMessage()); } diff --git a/android/java/org/chromium/chrome/browser/widget/crypto/binance/CryptoWidgetTabAdapter.java b/android/java/org/chromium/chrome/browser/widget/crypto/binance/CryptoWidgetTabAdapter.java index 538eaafdb87..4c84583ef2c 100644 --- a/android/java/org/chromium/chrome/browser/widget/crypto/binance/CryptoWidgetTabAdapter.java +++ b/android/java/org/chromium/chrome/browser/widget/crypto/binance/CryptoWidgetTabAdapter.java @@ -5,18 +5,25 @@ package org.chromium.chrome.browser.widget.crypto.binance; +import android.content.Context; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import android.view.ViewGroup; +import androidx.core.widget.NestedScrollView; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter; +import org.chromium.chrome.R; +import org.chromium.base.ContextUtils; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class CryptoWidgetTabAdapter extends FragmentStatePagerAdapter { - List titles = Arrays.asList("Summary", "Deposit", "Convert", "Buy"); + Context mContext = ContextUtils.getApplicationContext(); + List titles = Arrays.asList(mContext.getResources().getString(R.string.summary), mContext.getResources().getString(R.string.deposit), mContext.getResources().getString(R.string.convert), mContext.getResources().getString(R.string.buy)); public CryptoWidgetTabAdapter(@NonNull FragmentManager fm, int behavior) { super(fm, behavior); @@ -32,7 +39,7 @@ public class CryptoWidgetTabAdapter extends FragmentStatePagerAdapter { fragment = new BinanceDepositFragment(); } else if (position == 2) { fragment = new BinanceConvertFragment(); - } else if(position == 3) { + } else if (position == 3) { fragment = new BinanceBuyFragment(); } return fragment; @@ -48,4 +55,29 @@ public class CryptoWidgetTabAdapter extends FragmentStatePagerAdapter { public CharSequence getPageTitle(int position) { return titles.get(position); } + + @Override + public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + super.setPrimaryItem(container, position, object); + for (int i = 0; i < getCount(); i++) { + if ((NestedScrollView) container.findViewById(R.id.summary_scrollview) != null) { + ((NestedScrollView) container.findViewById(R.id.summary_scrollview)).setNestedScrollingEnabled(false); + } else if ((NestedScrollView) container.findViewById(R.id.deposit_scrollview) != null) { + ((NestedScrollView) container.findViewById(R.id.deposit_scrollview)).setNestedScrollingEnabled(false); + } + } + + Fragment currentFragment = (Fragment) object; + if (currentFragment.getView() != null) { + if (currentFragment.getClass() == BinanceSummaryFragment.class) { + NestedScrollView currentNestedScrollView = (NestedScrollView) currentFragment.getView().findViewById(R.id.summary_scrollview); + currentNestedScrollView.setNestedScrollingEnabled(true); + } else if (currentFragment.getClass() == BinanceDepositFragment.class) { + NestedScrollView currentNestedScrollView = (NestedScrollView) currentFragment.getView().findViewById(R.id.deposit_scrollview); + currentNestedScrollView.setNestedScrollingEnabled(true); + } + } + + container.requestLayout(); + } } \ No newline at end of file diff --git a/android/java/res/drawable/ic_add.xml b/android/java/res/drawable/ic_add.xml new file mode 100644 index 00000000000..01a02f4b390 --- /dev/null +++ b/android/java/res/drawable/ic_add.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/java/res/layout/brave_stats_layout.xml b/android/java/res/layout/brave_stats_layout.xml index 11de6cbfc29..e4301b2d258 100644 --- a/android/java/res/layout/brave_stats_layout.xml +++ b/android/java/res/layout/brave_stats_layout.xml @@ -44,6 +44,7 @@ android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" + android:gravity="center" android:orientation="horizontal" android:baselineAligned="false"> diff --git a/android/java/res/layout/crypto_widget_layout.xml b/android/java/res/layout/crypto_widget_layout.xml index 82ed9c64ffd..857628f8991 100644 --- a/android/java/res/layout/crypto_widget_layout.xml +++ b/android/java/res/layout/crypto_widget_layout.xml @@ -60,6 +60,7 @@ android:id="@+id/binance_widget_layout" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_gravity="center" android:visibility="gone" android:orientation="vertical"> diff --git a/android/java/res/layout/fragment_binance_deposit.xml b/android/java/res/layout/fragment_binance_deposit.xml index 7231ec398ad..94fe1e2eb83 100644 --- a/android/java/res/layout/fragment_binance_deposit.xml +++ b/android/java/res/layout/fragment_binance_deposit.xml @@ -7,9 +7,17 @@ - + + + + + \ No newline at end of file diff --git a/android/java/res/layout/fragment_binance_summary.xml b/android/java/res/layout/fragment_binance_summary.xml index 6e3c37db818..6786b6d51e6 100644 --- a/android/java/res/layout/fragment_binance_summary.xml +++ b/android/java/res/layout/fragment_binance_summary.xml @@ -38,9 +38,17 @@ android:layout_marginBottom="16dp" android:background="#c0c0c0"/> - + android:layout_height="match_parent"> + + + + \ No newline at end of file diff --git a/android/java/res/layout/fragment_crypto_widget_bottom_sheet_dialog.xml b/android/java/res/layout/fragment_crypto_widget_bottom_sheet_dialog.xml index b7713290139..892eedf85cb 100644 --- a/android/java/res/layout/fragment_crypto_widget_bottom_sheet_dialog.xml +++ b/android/java/res/layout/fragment_crypto_widget_bottom_sheet_dialog.xml @@ -33,6 +33,7 @@ android:padding="8dp" android:layout_gravity="center_vertical" android:contentDescription="@null" + android:visibility="gone" app:srcCompat="@drawable/ic_more_horiz"/> diff --git a/android/java/res/layout/fragment_ntp_widget_bottom_sheet_dialog.xml b/android/java/res/layout/fragment_ntp_widget_bottom_sheet_dialog.xml index be1af1c28d1..a1e3b443de5 100644 --- a/android/java/res/layout/fragment_ntp_widget_bottom_sheet_dialog.xml +++ b/android/java/res/layout/fragment_ntp_widget_bottom_sheet_dialog.xml @@ -21,7 +21,7 @@ android:text="@string/widget_stack" android:textSize="18sp" android:textStyle="bold" - android:textColor="@color/brave_stats_text_color"/> + android:textColor="@android:color/black"/> - - - + android:layout_height="wrap_content" + android:orientation="vertical"> - + + + android:layout_height="match_parent" + android:layout_margin="8dp" + app:cardBackgroundColor="#FFFFFF" + app:cardCornerRadius="14dp" + app:contentPadding="24dp"> - + + + + + diff --git a/android/java/res/layout/new_tab_page_layout.xml b/android/java/res/layout/new_tab_page_layout.xml index bcb0cc4aefc..2581d7ed9fe 100644 --- a/android/java/res/layout/new_tab_page_layout.xml +++ b/android/java/res/layout/new_tab_page_layout.xml @@ -66,7 +66,7 @@ diff --git a/android/java/res/layout/ntp_widget_list_item_layout.xml b/android/java/res/layout/ntp_widget_list_item_layout.xml index 2c0c72aa11d..efb66d037c0 100644 --- a/android/java/res/layout/ntp_widget_list_item_layout.xml +++ b/android/java/res/layout/ntp_widget_list_item_layout.xml @@ -39,7 +39,6 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:padding="8dp" - android:layout_marginStart="8dp" - app:srcCompat="@drawable/ic_sort" /> + android:layout_marginStart="8dp" /> \ No newline at end of file diff --git a/android/java/res/layout/top_sites_layout.xml b/android/java/res/layout/top_sites_layout.xml index 0e4704c3b56..c0edf47ff1e 100644 --- a/android/java/res/layout/top_sites_layout.xml +++ b/android/java/res/layout/top_sites_layout.xml @@ -43,7 +43,8 @@ + android:layout_height="wrap_content" + android:gravity="center"> \ No newline at end of file diff --git a/browser/ui/android/strings/android_brave_strings.grd b/browser/ui/android/strings/android_brave_strings.grd index 93f0b136201..92e047fad9b 100644 --- a/browser/ui/android/strings/android_brave_strings.grd +++ b/browser/ui/android/strings/android_brave_strings.grd @@ -1362,6 +1362,30 @@ until they verify, or until 90 days have passed. Retry + + Privacy Stats + + + Favorites + + + Binance + + + Trackers & Ads Blocked, Saved Bandwidth, and Time Saved Estimates. + + + Summary + + + Deposit + + + Convert + + + Buy +