add option to unlock all tips #888

Merged
akinwale merged 1 commit from unlock-tips into master 2020-05-24 00:39:17 +02:00
7 changed files with 228 additions and 17 deletions

View file

@ -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

View file

@ -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;
}
}

View file

@ -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<Void, Void, Boolean> {
private GenericTaskHandler handler;
private Exception error;
public UnlockTipsTask(GenericTaskHandler handler) {
this.handler = handler;
}
public Boolean doInBackground(Void... params) {
List<String> txids = new ArrayList<>();
List<String> claimIds = new ArrayList<>();
try {
Map<String, Object> 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);
}
}
}
}

View file

@ -23,16 +23,7 @@ public class WalletBalanceTask extends AsyncTask<Void, Void, WalletBalance> {
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;

View file

@ -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();

View file

@ -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";

View file

@ -160,12 +160,41 @@
android:textFontWeight="300"
android:textSize="14sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="16dp">
<TextView
android:id="@+id/wallet_in_tips_label"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/inter"
android:text="@string/in_tips"
android:textSize="14sp" />
<TextView
android:id="@+id/wallet_unlock_tips_link"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/wallet_in_tips_label"
android:fontFamily="@font/inter"
android:layout_marginLeft="24dp"
android:text="@string/unlock"
android:textColor="@color/lbryGreen"
android:textSize="14sp"
android:visibility="gone" />
<ProgressBar
android:id="@+id/wallet_unlock_tips_progress"
android:layout_centerVertical="true"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginLeft="24dp"
android:layout_toRightOf="@id/wallet_in_tips_label"
android:visibility="gone" />
</RelativeLayout>
<TextView
android:id="@+id/wallet_hint_earn_more_tips"