From 4bb9f5cb4355a422cb1bd795a8e4c392b36ef3e4 Mon Sep 17 00:00:00 2001 From: Akinwale Ariwodola Date: Sat, 23 May 2020 23:37:57 +0100 Subject: [PATCH] add option to unlock all tips --- .../java/io/lbry/browser/MainActivity.java | 42 +++++++++- .../io/lbry/browser/model/WalletBalance.java | 17 +++++ .../browser/tasks/wallet/UnlockTipsTask.java | 76 +++++++++++++++++++ .../tasks/wallet/WalletBalanceTask.java | 11 +-- .../browser/ui/wallet/WalletFragment.java | 55 ++++++++++++++ .../main/java/io/lbry/browser/utils/Lbry.java | 3 + .../main/res/layout/card_wallet_balance.xml | 41 ++++++++-- 7 files changed, 228 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/io/lbry/browser/tasks/wallet/UnlockTipsTask.java diff --git a/app/src/main/java/io/lbry/browser/MainActivity.java b/app/src/main/java/io/lbry/browser/MainActivity.java index ae1b023c..411174bc 100644 --- a/app/src/main/java/io/lbry/browser/MainActivity.java +++ b/app/src/main/java/io/lbry/browser/MainActivity.java @@ -66,7 +66,6 @@ import androidx.core.app.NotificationManagerCompat; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import androidx.core.content.res.ResourcesCompat; -import androidx.core.graphics.TypefaceCompat; import androidx.core.graphics.drawable.DrawableCompat; import androidx.core.view.GravityCompat; import androidx.core.view.OnApplyWindowInsetsListener; @@ -129,6 +128,7 @@ import io.lbry.browser.model.WalletBalance; import io.lbry.browser.model.WalletSync; import io.lbry.browser.model.lbryinc.Reward; import io.lbry.browser.model.lbryinc.Subscription; +import io.lbry.browser.tasks.GenericTaskHandler; import io.lbry.browser.tasks.claim.ClaimListResultHandler; import io.lbry.browser.tasks.claim.ClaimListTask; import io.lbry.browser.tasks.lbryinc.ClaimRewardTask; @@ -143,6 +143,7 @@ import io.lbry.browser.tasks.wallet.SaveSharedUserStateTask; import io.lbry.browser.tasks.wallet.SyncApplyTask; import io.lbry.browser.tasks.wallet.SyncGetTask; import io.lbry.browser.tasks.wallet.SyncSetTask; +import io.lbry.browser.tasks.wallet.UnlockTipsTask; import io.lbry.browser.tasks.wallet.WalletBalanceTask; import io.lbry.browser.ui.BaseFragment; import io.lbry.browser.ui.channel.ChannelFormFragment; @@ -182,6 +183,10 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener private boolean inPictureInPictureMode; @Getter private boolean inFullscreenMode; + // make tip unlock a global operation + @Getter + private boolean unlockingTips; + public static SimpleExoPlayer appPlayer; public static Cache playerCache; public static boolean playerReassigned; @@ -2812,6 +2817,41 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + public void unlockTips() { + if (unlockingTips) { + return; + } + UnlockTipsTask task = new UnlockTipsTask(new GenericTaskHandler() { + @Override + public void beforeStart() { + unlockingTips = true; + } + + @Override + public void onSuccess() { + unlockingTips = false; + for (Fragment fragment : openNavFragments.values()) { + if (fragment instanceof WalletFragment) { + ((WalletFragment) fragment).checkTips(true); + } + } + } + + @Override + public void onError(Exception error) { + unlockingTips = false; + for (Fragment fragment : openNavFragments.values()) { + if (fragment instanceof WalletFragment) { + ((WalletFragment) fragment).checkTips(); + } + } + // fail silently? + //showError(error.getMessage()); + } + }); + task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + private void checkSyncedWallet() { String password = Utils.getSecureValue(SECURE_VALUE_KEY_SAVED_PASSWORD, this, Lbry.KEYSTORE); // Just check if the current user has a synced wallet, no need to do anything else here diff --git a/app/src/main/java/io/lbry/browser/model/WalletBalance.java b/app/src/main/java/io/lbry/browser/model/WalletBalance.java index 993a0c31..c2102b70 100644 --- a/app/src/main/java/io/lbry/browser/model/WalletBalance.java +++ b/app/src/main/java/io/lbry/browser/model/WalletBalance.java @@ -1,7 +1,10 @@ package io.lbry.browser.model; +import org.json.JSONObject; + import java.math.BigDecimal; +import io.lbry.browser.utils.Helper; import lombok.Data; @Data @@ -21,4 +24,18 @@ public class WalletBalance { tips = new BigDecimal(0); total = new BigDecimal(0); } + + public static WalletBalance fromJSONObject(JSONObject json) { + WalletBalance balance = new WalletBalance(); + JSONObject reservedSubtotals = Helper.getJSONObject("reserved_subtotals", json); + balance.setAvailable(new BigDecimal(Helper.getJSONString("available", "0", json))); + balance.setReserved(new BigDecimal(Helper.getJSONString("reserved", "0", json))); + balance.setTotal(new BigDecimal(Helper.getJSONString("total", "0", json))); + if (reservedSubtotals != null) { + balance.setClaims(new BigDecimal(Helper.getJSONString("claims", "0", reservedSubtotals))); + balance.setSupports(new BigDecimal(Helper.getJSONString("supports", "0", reservedSubtotals))); + balance.setTips(new BigDecimal(Helper.getJSONString("tips", "0", reservedSubtotals))); + } + return balance; + } } diff --git a/app/src/main/java/io/lbry/browser/tasks/wallet/UnlockTipsTask.java b/app/src/main/java/io/lbry/browser/tasks/wallet/UnlockTipsTask.java new file mode 100644 index 00000000..a3b53298 --- /dev/null +++ b/app/src/main/java/io/lbry/browser/tasks/wallet/UnlockTipsTask.java @@ -0,0 +1,76 @@ +package io.lbry.browser.tasks.wallet; + +import android.os.AsyncTask; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.lbry.browser.exceptions.ApiCallException; +import io.lbry.browser.model.WalletBalance; +import io.lbry.browser.tasks.GenericTaskHandler; +import io.lbry.browser.utils.Helper; +import io.lbry.browser.utils.Lbry; + +public class UnlockTipsTask extends AsyncTask { + + private GenericTaskHandler handler; + private Exception error; + + public UnlockTipsTask(GenericTaskHandler handler) { + this.handler = handler; + } + + public Boolean doInBackground(Void... params) { + + List txids = new ArrayList<>(); + List claimIds = new ArrayList<>(); + + try { + Map options = new HashMap<>(); + options.put("type", "support"); + options.put("is_not_my_input", true); + options.put("is_my_output", true); + JSONObject result = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_TXO_LIST, options); + if (result.has("items") && !result.isNull("items")) { + JSONArray items = result.getJSONArray("items"); + for (int i = 0; i < items.length(); i++) { + JSONObject item = items.getJSONObject(i); + String txid = Helper.getJSONString("txid", null, item); + String claimId = Helper.getJSONString("claim_id", null, item); + if (!Helper.isNullOrEmpty(txid) && !Helper.isNullOrEmpty(claimId)) { + txids.add(txid); + claimIds.add(claimId); + } + } + } + + if (txids.size() > 0 && txids.size() == claimIds.size()) { + options = new HashMap<>(); + options.put("txid", txids); + options.put("claim_id", claimIds); + Lbry.genericApiCall(Lbry.METHOD_TXO_SPEND, options); + } + + return true; + } catch (ApiCallException | ClassCastException | JSONException ex) { + error = ex; + return false; + } + } + + protected void onPostExecute(Boolean result) { + if (handler != null) { + if (result) { + handler.onSuccess(); + } else { + handler.onError(error); + } + } + } +} diff --git a/app/src/main/java/io/lbry/browser/tasks/wallet/WalletBalanceTask.java b/app/src/main/java/io/lbry/browser/tasks/wallet/WalletBalanceTask.java index 09d26c42..53eb94e8 100644 --- a/app/src/main/java/io/lbry/browser/tasks/wallet/WalletBalanceTask.java +++ b/app/src/main/java/io/lbry/browser/tasks/wallet/WalletBalanceTask.java @@ -23,16 +23,7 @@ public class WalletBalanceTask extends AsyncTask { WalletBalance balance = new WalletBalance(); try { JSONObject json = (JSONObject) Lbry.genericApiCall(Lbry.METHOD_WALLET_BALANCE); - JSONObject reservedSubtotals = Helper.getJSONObject("reserved_subtotals", json); - - balance.setAvailable(new BigDecimal(Helper.getJSONString("available", "0", json))); - balance.setReserved(new BigDecimal(Helper.getJSONString("reserved", "0", json))); - balance.setTotal(new BigDecimal(Helper.getJSONString("total", "0", json))); - if (reservedSubtotals != null) { - balance.setClaims(new BigDecimal(Helper.getJSONString("claims", "0", reservedSubtotals))); - balance.setSupports(new BigDecimal(Helper.getJSONString("supports", "0", reservedSubtotals))); - balance.setTips(new BigDecimal(Helper.getJSONString("tips", "0", reservedSubtotals))); - } + balance = WalletBalance.fromJSONObject(json); } catch (ApiCallException | ClassCastException ex) { error = ex; return null; diff --git a/app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java b/app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java index 24a3e2b9..95a84eb6 100644 --- a/app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/wallet/WalletFragment.java @@ -3,6 +3,7 @@ package io.lbry.browser.ui.wallet; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.graphics.Color; import android.os.AsyncTask; @@ -17,6 +18,7 @@ import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.DividerItemDecoration; @@ -66,6 +68,9 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W private TextView textSupportsBalance; private ProgressBar walletSendProgress; + private TextView linkUnlockTips; + private ProgressBar progressUnlockTips; + private View loadingRecentContainer; private View inlineBalanceContainer; private TextView textWalletInlineBalance; @@ -114,6 +119,9 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W textSupportsBalance = root.findViewById(R.id.wallet_balance_staked_supports); textWalletHintSyncStatus = root.findViewById(R.id.wallet_hint_sync_status); + linkUnlockTips = root.findViewById(R.id.wallet_unlock_tips_link); + progressUnlockTips = root.findViewById(R.id.wallet_unlock_tips_progress); + recentTransactionsList = root.findViewById(R.id.wallet_recent_transactions_list); linkViewAll = root.findViewById(R.id.wallet_link_view_all); textNoRecentTransactions = root.findViewById(R.id.wallet_no_recent_transactions); @@ -242,6 +250,24 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W itemDecoration.setDrawable(ContextCompat.getDrawable(context, R.drawable.thin_divider)); recentTransactionsList.addItemDecoration(itemDecoration); + linkUnlockTips.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (context != null) { + AlertDialog.Builder builder = new AlertDialog.Builder(context). + setTitle(R.string.unlock_tips). + setMessage(R.string.confirm_unlock_tips) + .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + unlockTips(); + } + }).setNegativeButton(R.string.no, null); + builder.show(); + } + } + }); + textEarnMoreTips.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -492,6 +518,7 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W checkReceiveAddress(); checkRewardsDriver(); + checkTips(); fetchRecentTransactions(); } @@ -535,9 +562,37 @@ public class WalletFragment extends BaseFragment implements SdkStatusListener, W Helper.setViewText(textTipsBalanceUSD, String.format("≈$%s", Helper.SIMPLE_CURRENCY_FORMAT.format(tipsUsdBalance))); } + checkTips(); checkRewardsDriver(); } + private void unlockTips() { + Context context = getContext(); + if (context instanceof MainActivity) { + linkUnlockTips.setVisibility(View.GONE); + progressUnlockTips.setVisibility(View.VISIBLE); + ((MainActivity) context).unlockTips(); + } + } + + public void checkTips() { + checkTips(false); + } + + public void checkTips(boolean forceHideLink) { + WalletBalance walletBalance = Lbry.walletBalance; + double tipBalance = walletBalance == null ? 0 : walletBalance.getTips().doubleValue(); + boolean unlocking = false; + Context context = getContext(); + if (context instanceof MainActivity) { + MainActivity activity = (MainActivity) context; + unlocking = activity.isUnlockingTips(); + } + + Helper.setViewVisibility(linkUnlockTips, !forceHideLink && tipBalance > 0 && !unlocking ? View.VISIBLE : View.GONE); + Helper.setViewVisibility(progressUnlockTips, unlocking ? View.VISIBLE : View.GONE); + } + private void checkRewardsDriver() { // check rewards driver Context ctx = getContext(); diff --git a/app/src/main/java/io/lbry/browser/utils/Lbry.java b/app/src/main/java/io/lbry/browser/utils/Lbry.java index ec2ed59d..7f6df825 100644 --- a/app/src/main/java/io/lbry/browser/utils/Lbry.java +++ b/app/src/main/java/io/lbry/browser/utils/Lbry.java @@ -88,6 +88,9 @@ public final class Lbry { public static final String METHOD_PREFERENCE_GET = "preference_get"; public static final String METHOD_PREFERENCE_SET = "preference_set"; + public static final String METHOD_TXO_LIST = "txo_list"; + public static final String METHOD_TXO_SPEND = "txo_spend"; + public static final String METHOD_CHANNEL_ABANDON = "channel_abandon"; public static final String METHOD_CHANNEL_CREATE = "channel_create"; public static final String METHOD_CHANNEL_UPDATE = "channel_update"; diff --git a/app/src/main/res/layout/card_wallet_balance.xml b/app/src/main/res/layout/card_wallet_balance.xml index 3468bdad..8e07d85f 100644 --- a/app/src/main/res/layout/card_wallet_balance.xml +++ b/app/src/main/res/layout/card_wallet_balance.xml @@ -160,12 +160,41 @@ android:textFontWeight="300" android:textSize="14sp" /> - + + + + + +