@ -4,17 +4,22 @@ package com.alphawallet.app.ui;
import android.content.Context ;
import android.content.Intent ;
import android.os.Bundle ;
import android.os.Handler ;
import android.text.format.DateUtils ;
import android.view.LayoutInflater ;
import android.view.Menu ;
import android.view.MenuItem ;
import android.view.View ;
import android.view.ViewGroup ;
import android.widget.EditText ;
import android.widget.FrameLayout ;
import android.widget.ImageView ;
import android.widget.LinearLayout ;
import android.widget.ScrollView ;
import android.widget.TextView ;
import androidx.annotation.Nullable ;
import androidx.core.content.ContextCompat ;
import androidx.lifecycle.ViewModelProvider ;
import androidx.recyclerview.widget.LinearLayoutManager ;
import androidx.recyclerview.widget.RecyclerView ;
@ -30,6 +35,7 @@ import com.alphawallet.app.service.TickerService;
import com.alphawallet.app.ui.widget.divider.ListDivider ;
import com.alphawallet.app.ui.widget.entity.GasSettingsCallback ;
import com.alphawallet.app.ui.widget.entity.GasSpeed ;
import com.alphawallet.app.ui.widget.entity.GasWarningLayout ;
import com.alphawallet.app.util.BalanceUtils ;
import com.alphawallet.app.util.Utils ;
import com.alphawallet.app.viewmodel.GasSettingsViewModel ;
@ -71,7 +77,10 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
private BigDecimal availableBalance ;
private BigDecimal sendAmount ;
private BigInteger customGasPriceFromWidget ;
private final BigInteger minGas = BigInteger . valueOf ( C . GAS_PRICE_MIN ) ;
private GasWarningLayout gasWarning ;
private GasWarningLayout insufficientWarning ;
private ScrollView scroll ;
private final Handler handler = new Handler ( ) ;
private int customIndex = - 1 ;
@ -86,6 +95,9 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
gasSliderView = findViewById ( R . id . gasSliderView ) ;
recyclerView = findViewById ( R . id . list ) ;
gasWarning = findViewById ( R . id . gas_warning_bubble ) ;
insufficientWarning = findViewById ( R . id . insufficient_bubble ) ;
scroll = findViewById ( R . id . setting_scroll ) ;
recyclerView . setLayoutManager ( new LinearLayoutManager ( this ) ) ;
viewModel = new ViewModelProvider ( this , viewModelFactory )
@ -127,6 +139,7 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
{
GasPriceSpread gs = ( ( RealmGasSpread ) realmToken ) . getGasPrice ( ) ;
initGasSpeeds ( gs ) ;
gasSettingsUpdate ( gasSpeeds . get ( customIndex ) . gasPrice , customGasLimit . toBigInteger ( ) ) ;
}
} ) ;
}
@ -231,7 +244,6 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
final TextView speedCostEth ;
final TextView speedCostFiat ;
final TextView speedTime ;
final LinearLayout blankOverlay ;
final View itemLayout ;
CustomViewHolder ( View view )
@ -244,7 +256,6 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
speedTime = view . findViewById ( R . id . text_speed_time ) ;
itemLayout = view . findViewById ( R . id . layout_list_item ) ;
speedGwei = view . findViewById ( R . id . text_gwei ) ;
blankOverlay = view . findViewById ( R . id . layout_overlay ) ;
}
}
@ -264,12 +275,16 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
holder . itemLayout . setOnClickListener ( v - > {
if ( position = = customIndex & & currentGasSpeedIndex ! = customIndex )
{
if ( holder . blankOverlay . getVisibility ( ) = = View . VISIBLE ) { return ; } //don't allow selection of invalid amount
gasSliderView . initGasLimit ( customGasLimit . toBigInteger ( ) ) ;
gasSliderView . reportPosition ( ) ;
}
else if ( position ! = customIndex & & currentGasSpeedIndex = = customIndex )
{
hideGasWarning ( ) ;
}
currentGasSpeedIndex = position ;
notifyDataSetChanged ( ) ;
} ) ;
String speedGwei = BalanceUtils . weiToGweiBI ( gs . gasPrice ) . toBigInteger ( ) . toString ( ) ;
@ -291,6 +306,7 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
}
}
BigDecimal gasFee = new BigDecimal ( gs . gasPrice ) . multiply ( useGasLimit ) ;
String gasAmountInBase = BalanceUtils . getScaledValueScientific ( gasFee , baseCurrency . tokenInfo . decimals , GAS_PRECISION ) ;
@ -318,15 +334,7 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
//determine if this amount can be used
BigDecimal txCost = gasFee . add ( sendAmount ) ;
if ( txCost . compareTo ( availableBalance ) > = 0 )
{
//cannot be used
holder . blankOverlay . setVisibility ( View . VISIBLE ) ;
}
else
{
holder . blankOverlay . setVisibility ( View . GONE ) ;
}
checkInsufficientGas ( txCost ) ;
}
private void blankCustomHolder ( CustomViewHolder holder )
@ -378,8 +386,10 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
gasSliderView . initGasPriceMax ( gs . gasPrice ) ;
notice . setVisibility ( View . VISIBLE ) ;
gasSliderView . setVisibility ( View . GONE ) ;
hideGasWarning ( ) ;
}
}
}
@Override
@ -410,23 +420,39 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
expectedTime = ( long ) ( ( double ) lg . seconds - extrapolateFactor * timeDiff ) ;
break ;
}
else if ( lg . speed . equals ( getString ( R . string . speed_slow ) ) & & dGasPrice < lowerBound )
{
else if ( lg . speed . equals ( getString ( R . string . speed_slow ) ) ) { //final entry
//danger zone - transaction may not complete
double dangerAmount = lowerBound / 2 . 0 ;
long dangerTime = 12 * DateUtils . HOUR_IN_MILLIS / 1000 ;
if ( dGasPrice < dangerAmount )
if ( dGasPrice < ( lowerBound * 0 . 95 ) ) //only show gas warning if less than 95% of slow
{
showGasWarning ( false ) ;
}
if ( dGasPrice < dangerAmount ) {
expectedTime = - 1 ; //never
} else {
expectedTime = extrapolateTime ( dangerTime , lg . seconds , dGasPrice , dangerAmount , lowerBound ) ;
}
return expectedTime ;
}
else if ( ug . speed . equals ( getString ( R . string . speed_rapid ) ) & & dGasPrice > = upperBound )
{
if ( dGasPrice > 1 . 4 * upperBound )
{
showGasWarning ( true ) ; //only show gas warning if greater than 140% of max needed gas
}
else
{
expectedTime = extrapolateTime ( dangerTime , lg . seconds , dGasPrice , dangerAmount , lowerBound ) ;
hideGasWarning ( ) ;
}
break ;
return expectedTime ; //exit here so we don't hit the speed_slow catcher
}
}
hideGasWarning ( ) ; // Didn't need a gas warning: custom gas is within bounds
}
return expectedTime ;
@ -441,7 +467,10 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
private void updateCustomElement ( BigInteger gasPrice , BigInteger gasLimit )
{
if ( customIndex < 0 ) return ;
if ( customIndex < 0 )
{
return ;
}
GasSpeed gs = gasSpeeds . get ( customIndex ) ;
//new settings from the slider widget
gs = new GasSpeed ( gs . speed , getExpectedTransactionTime ( gasPrice ) , gasPrice , true ) ;
@ -450,4 +479,68 @@ public class GasSettingsActivity extends BaseActivity implements GasSettingsCall
this . customGasLimit = new BigDecimal ( gasLimit ) ;
}
private void showGasWarning ( boolean high )
{
if ( currentGasSpeedIndex ! = customIndex )
{
return ;
}
displayGasWarning ( ) ; //if gas warning already showing, no need to take focus from user input
TextView heading = findViewById ( R . id . bubble_title ) ;
TextView body = findViewById ( R . id . bubble_body ) ;
if ( high )
{
heading . setText ( getString ( R . string . high_gas_setting ) ) ;
body . setText ( getString ( R . string . body_high_gas ) ) ;
}
else
{
heading . setText ( getString ( R . string . low_gas_setting ) ) ;
body . setText ( getString ( R . string . body_low_gas ) ) ;
}
}
private void displayGasWarning ( )
{
if ( gasWarning . getVisibility ( ) ! = View . VISIBLE ) //no need to re-apply
{
handler . postDelayed ( ( ) - > scroll . fullScroll ( View . FOCUS_DOWN ) , 100 ) ;
gasWarning . setVisibility ( View . VISIBLE ) ;
EditText gas_price_entry = findViewById ( R . id . gas_price_entry ) ;
gas_price_entry . setTextColor ( getColor ( R . color . danger ) ) ;
gas_price_entry . setBackground ( ContextCompat . getDrawable ( this , R . drawable . background_text_edit_error ) ) ;
}
}
private void hideGasWarning ( )
{
gasWarning . setVisibility ( View . GONE ) ;
EditText gas_price_entry = findViewById ( R . id . gas_price_entry ) ;
gas_price_entry . setTextColor ( getColor ( R . color . dove ) ) ;
gas_price_entry . setBackground ( getDrawable ( R . drawable . background_password_entry ) ) ;
}
private void checkInsufficientGas ( BigDecimal txCost )
{
if ( txCost . compareTo ( availableBalance ) > 0 )
{
insufficientWarning . setVisibility ( View . VISIBLE ) ;
}
else
{
insufficientWarning . setVisibility ( View . GONE ) ;
}
if ( insufficientWarning . getVisibility ( ) = = View . VISIBLE & & gasWarning . getVisibility ( ) = = View . VISIBLE )
{
gasWarning . setVisibility ( View . GONE ) ;
}
}
}