Merge branch 'feat_ui_improvements' of https://github.com/Agorise/crystal-wallet-android into develop
This commit is contained in:
commit
a7ba6f5c6b
20 changed files with 618 additions and 371 deletions
|
@ -18,8 +18,7 @@
|
|||
android:configChanges="locale"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".activities.LicenseActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
android:name=".activities.LicenseActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import butterknife.BindView;
|
|||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.fragments.BackupsSettingsFragment;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.viewmodels.AccountSeedViewModel;
|
||||
|
||||
|
@ -28,7 +29,7 @@ public class BackupSeedActivity extends AppCompatActivity {
|
|||
|
||||
@BindView(R.id.tvBrainKey)
|
||||
TextView textfieldBrainkey;
|
||||
@BindView(R.id.btnOk)
|
||||
@BindView(R.id.btnCancel)
|
||||
Button btnOk;
|
||||
@BindView(R.id.btnCopy)
|
||||
Button btnCopy;
|
||||
|
@ -60,14 +61,14 @@ public class BackupSeedActivity extends AppCompatActivity {
|
|||
accountSeedViewModel.loadSeed(seedId);
|
||||
|
||||
} else {
|
||||
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btnOk)
|
||||
@OnClick(R.id.btnCancel)
|
||||
public void btnOkClick(){
|
||||
Intent intent = new Intent(this, IntroActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -13,6 +13,7 @@ import cy.agorise.crystalwallet.R
|
|||
import cy.agorise.crystalwallet.dialogs.material.CrystalDialog
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateCreateBitsharesAccountRequest
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountRequest
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidatorListener
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields.BitsharesAccountNameValidation
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields.BitsharesAccountNameValidation.OnAccountExist
|
||||
|
@ -62,16 +63,12 @@ class CreateSeedActivity : CustomActivity() {
|
|||
runOnUiThread {
|
||||
val customTextInputEditText = customValidationField.currentView as CustomTextInputEditText
|
||||
customTextInputEditText.error = null
|
||||
customTextInputEditText.fieldValidatorModel.setValid()
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate if can continue
|
||||
* */
|
||||
validateFieldsToContinue()
|
||||
}
|
||||
|
||||
override fun onValidationFailed(customValidationField: CustomValidationField) {
|
||||
|
@ -82,6 +79,7 @@ class CreateSeedActivity : CustomActivity() {
|
|||
runOnUiThread {
|
||||
val customTextInputEditText = customValidationField.currentView as CustomTextInputEditText
|
||||
customTextInputEditText.error = customTextInputEditText.fieldValidatorModel.message
|
||||
customTextInputEditText.fieldValidatorModel.setInvalid()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +129,8 @@ class CreateSeedActivity : CustomActivity() {
|
|||
* Validate continue to create account
|
||||
* */
|
||||
validateFieldsToContinue()
|
||||
|
||||
|
||||
}
|
||||
|
||||
@OnTextChanged(value = R.id.tietPinConfirmation, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
|
@ -148,9 +148,9 @@ class CreateSeedActivity : CustomActivity() {
|
|||
this.fieldsValidator.validate()
|
||||
|
||||
/*
|
||||
* Always disable till the server response comes
|
||||
* Validate continue to create account
|
||||
* */
|
||||
disableCreate()
|
||||
validateFieldsToContinue()
|
||||
}
|
||||
|
||||
@OnClick(R.id.btnCancel)
|
||||
|
@ -221,8 +221,59 @@ class CreateSeedActivity : CustomActivity() {
|
|||
* If the result is true so the user can continue to the creation of the account
|
||||
* */
|
||||
if (result) {
|
||||
enableCreate()
|
||||
|
||||
/*
|
||||
* Show the dialog for connection with the server
|
||||
* */
|
||||
val creatingAccountMaterialDialog = CrystalDialog(globalActivity)
|
||||
creatingAccountMaterialDialog.setText(globalActivity.resources.getString(R.string.window_create_seed_Server_validation))
|
||||
creatingAccountMaterialDialog.progress()
|
||||
creatingAccountMaterialDialog.show()
|
||||
|
||||
/*
|
||||
* Validate the account does not exists
|
||||
* */
|
||||
val request = ValidateExistBitsharesAccountRequest(tietAccountName?.text.toString())
|
||||
request.setListener {
|
||||
|
||||
/*
|
||||
* Dismiss the dialog of loading
|
||||
* */
|
||||
creatingAccountMaterialDialog.dismiss()
|
||||
|
||||
if (request.accountExists) {
|
||||
|
||||
/*
|
||||
* The account exists and is not valid
|
||||
* */
|
||||
tietAccountName.fieldValidatorModel.setInvalid()
|
||||
tietAccountName.fieldValidatorModel.message = tietAccountName.resources.getString(R.string.account_name_already_exist)
|
||||
|
||||
/*
|
||||
* Disaible button create
|
||||
* */
|
||||
disableCreate()
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Passed all validations
|
||||
* */
|
||||
tietAccountName.fieldValidatorModel.setValid()
|
||||
|
||||
/*
|
||||
* Enable button create
|
||||
* */
|
||||
enableCreate()
|
||||
}
|
||||
}
|
||||
CryptoNetInfoRequests.getInstance().addRequest(request)
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Disaible button create
|
||||
* */
|
||||
disableCreate()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Date;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import cy.agorise.crystalwallet.application.constant.BitsharesConstant;
|
||||
import cy.agorise.crystalwallet.dao.BitsharesAssetDao;
|
||||
import cy.agorise.crystalwallet.dao.CryptoCoinBalanceDao;
|
||||
import cy.agorise.crystalwallet.dao.CryptoCurrencyDao;
|
||||
|
@ -80,8 +81,6 @@ public abstract class GrapheneApiGenerator {
|
|||
*/
|
||||
private static HashMap<Long,SubscriptionListener> currentBitsharesListener = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the data of an account searching by it's id
|
||||
*
|
||||
|
@ -129,10 +128,7 @@ public abstract class GrapheneApiGenerator {
|
|||
List<UserAccount> accounts = resp.get(0);
|
||||
if(accounts.size() > 0){
|
||||
for(UserAccount account : accounts) {
|
||||
request.getListener().success(account, request.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
request.getListener().success(account,request.getId());}}}
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
|
||||
|
@ -296,7 +292,6 @@ public abstract class GrapheneApiGenerator {
|
|||
|
||||
/**
|
||||
* Gets the asset ifnormation using the id of the net
|
||||
*
|
||||
* @param assetIds The list of the ids to retrieve
|
||||
* @param request the api request object, to answer this petition
|
||||
*/
|
||||
|
@ -417,23 +412,17 @@ public abstract class GrapheneApiGenerator {
|
|||
|
||||
currentBitsharesListener.put(accountId,balanceListener);
|
||||
bitsharesSubscriptionHub.addSubscriptionListener(balanceListener);
|
||||
try {
|
||||
if (!subscriptionThread.isConnected() && !subscriptionThread.isAlive()) {
|
||||
|
||||
if(!subscriptionThread.isConnected()){
|
||||
subscriptionThread.start();
|
||||
|
||||
} else if (bitsharesSubscriptionHub != null && !bitsharesSubscriptionHub.isSubscribed()) {
|
||||
}else if(!bitsharesSubscriptionHub.isSubscribed()){
|
||||
bitsharesSubscriptionHub.resubscribe();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to save a transaction retrieved from the update
|
||||
*
|
||||
* @param transaction The transaction db object
|
||||
* @param currency The currency of the transaccion
|
||||
* @param accountBitsharesId The id of the account in the bitshares network
|
||||
|
@ -584,7 +573,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}), CryptoNetManager.getURL(CryptoNet.BITSHARES)); //todo change equivalent url for current server url
|
||||
}), BitsharesConstant.EQUIVALENT_URL); //todo change equivalent url for current server url
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
@ -600,7 +589,7 @@ public abstract class GrapheneApiGenerator {
|
|||
for(BitsharesAsset quoteAsset : quoteAssets){
|
||||
WebSocketThread thread = new WebSocketThread(new GetLimitOrders(baseAsset.getBitsharesId(),
|
||||
quoteAsset.getBitsharesId(), 10, new EquivalentValueListener(baseAsset,
|
||||
quoteAsset, context)), CryptoNetManager.getURL(CryptoNet.BITSHARES)); //todo change equivalent url for current server url
|
||||
quoteAsset,context)), BitsharesConstant.EQUIVALENT_URL); //todo change equivalent url for current server url
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
@ -703,4 +692,5 @@ public abstract class GrapheneApiGenerator {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -43,6 +43,7 @@ open abstract class DialogMaterial{
|
|||
* Init the builder
|
||||
* */
|
||||
builder = MaterialDialog.Builder(activity)
|
||||
builder.cancelable(false)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2,6 +2,7 @@ package cy.agorise.crystalwallet.fragments;
|
|||
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.Nullable;
|
||||
|
@ -24,6 +25,8 @@ import butterknife.BindView;
|
|||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.activities.BackupSeedActivity;
|
||||
import cy.agorise.crystalwallet.activities.IntroActivity;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CreateBackupRequest;
|
||||
|
@ -47,6 +50,9 @@ public class BackupsSettingsFragment extends Fragment{
|
|||
return fragment;
|
||||
}
|
||||
|
||||
@BindView(R.id.btnBrainkey)
|
||||
public Button btnBrainkey;
|
||||
|
||||
@BindView(R.id.tvBinFile)
|
||||
public TextView tvBinFile;
|
||||
|
||||
|
@ -81,6 +87,15 @@ public class BackupsSettingsFragment extends Fragment{
|
|||
return ssb;
|
||||
}
|
||||
|
||||
|
||||
@OnClick(R.id.btnBrainkey)
|
||||
public void btnBrainOnClick(){
|
||||
|
||||
Intent intent = new Intent(getContext(), BackupSeedActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
@OnClick(R.id.btnBinFile)
|
||||
public void makeBackupFile(){
|
||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
|
|
|
@ -56,7 +56,10 @@ public class SecuritySettingsFragment extends Fragment {
|
|||
return fragment;
|
||||
}
|
||||
|
||||
private NfcAdapter mNfcAdapter;
|
||||
/*
|
||||
* Functionality not needed for now
|
||||
* */
|
||||
//private NfcAdapter mNfcAdapter;
|
||||
private PendingIntent pendingIntent;
|
||||
private IntentFilter ndef;
|
||||
IntentFilter[] intentFiltersArray;
|
||||
|
@ -100,7 +103,11 @@ public class SecuritySettingsFragment extends Fragment {
|
|||
mPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mPager));
|
||||
|
||||
mNfcAdapter = NfcAdapter.getDefaultAdapter(this.getActivity());
|
||||
/*
|
||||
* Functionality not needed for now
|
||||
* */
|
||||
//mNfcAdapter = NfcAdapter.getDefaultAdapter(this.getActivity());
|
||||
|
||||
this.configureForegroundDispatch();
|
||||
|
||||
return v;
|
||||
|
@ -149,32 +156,37 @@ public class SecuritySettingsFragment extends Fragment {
|
|||
}
|
||||
|
||||
public void configureForegroundDispatch(){
|
||||
if (mNfcAdapter != null) {
|
||||
pendingIntent = PendingIntent.getActivity(
|
||||
this.getActivity(), 0, new Intent(this.getActivity(), getActivity().getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
|
||||
|
||||
ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
|
||||
try {
|
||||
ndef.addDataType("*/*"); /* Handles all MIME based dispatches.
|
||||
You should specify only the ones that you need. */
|
||||
} catch (IntentFilter.MalformedMimeTypeException e) {
|
||||
throw new RuntimeException("fail", e);
|
||||
}
|
||||
intentFiltersArray = new IntentFilter[]{ndef,};
|
||||
techList = new String[][]{ new String[] {IsoDep.class.getName(), NfcA.class.getName(), MifareClassic.class.getName(), NdefFormatable.class.getName()} };
|
||||
/*
|
||||
* Functionality not needed for now
|
||||
* */
|
||||
//if (mNfcAdapter != null) {
|
||||
//pendingIntent = PendingIntent.getActivity(
|
||||
// this.getActivity(), 0, new Intent(this.getActivity(), getActivity().getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
|
||||
|
||||
} else {
|
||||
Toast.makeText(this.getContext(), "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
//ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
|
||||
//try {
|
||||
//ndef.addDataType("*/*");
|
||||
// Handles all MIME based dispatches.
|
||||
//You should specify only the ones that you need.
|
||||
//} catch (IntentFilter.MalformedMimeTypeException e) {
|
||||
//throw new RuntimeException("fail", e);
|
||||
//}
|
||||
//intentFiltersArray = new IntentFilter[]{ndef,};
|
||||
//techList = new String[][]{ new String[] {IsoDep.class.getName(), NfcA.class.getName(), MifareClassic.class.getName(), NdefFormatable.class.getName()} };
|
||||
|
||||
//} else {
|
||||
//Toast.makeText(this.getContext(), "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
|
||||
//}
|
||||
}
|
||||
|
||||
public void enableNfc(){
|
||||
mNfcAdapter.enableForegroundDispatch(this.getActivity(), pendingIntent, intentFiltersArray, techList);
|
||||
//mNfcAdapter.enableForegroundDispatch(this.getActivity(), pendingIntent, intentFiltersArray, techList);
|
||||
Toast.makeText(this.getContext(), "Tap with your yubikey", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
public void disableNfc(){
|
||||
mNfcAdapter.disableForegroundDispatch(this.getActivity());
|
||||
//mNfcAdapter.disableForegroundDispatch(this.getActivity());
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
|
@ -184,9 +196,9 @@ public class SecuritySettingsFragment extends Fragment {
|
|||
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (mNfcAdapter != null) {
|
||||
/*if (mNfcAdapter != null) {
|
||||
enableNfc();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public void onNewIntent(Intent intent) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package cy.agorise.crystalwallet.network;
|
||||
|
||||
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.graphenej.interfaces.WitnessResponseListener;
|
||||
import cy.agorise.graphenej.models.BaseResponse;
|
||||
|
@ -24,21 +23,15 @@ public class BitsharesCryptoNetVerifier extends CryptoNetVerifier {
|
|||
private final String CHAIN_ID = "9cf6f255a208100d2bb275a3c52f4b1589b7ec9c9bfc2cb2a5fe6411295106d8";//testnet
|
||||
//private final String CHAIN_ID = "4018d7844c78f6a6c41c6a552b898022310fc5dec06da467ee7905a8dad512c8";//mainnet
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public BitsharesCryptoNetVerifier(){
|
||||
|
||||
/**/
|
||||
@Override
|
||||
public void checkURL(final String url) {
|
||||
final long startTime = System.currentTimeMillis();
|
||||
thread = new WebSocketThread(new GetChainId(new WitnessResponseListener() {
|
||||
WebSocketThread thread = new WebSocketThread(new GetChainId(new WitnessResponseListener() {
|
||||
@Override
|
||||
public void onSuccess(WitnessResponse response) {
|
||||
if(response.result instanceof String) {
|
||||
if(response.result.equals(CHAIN_ID)) {
|
||||
CryptoNetManager.verifiedCryptoNetURL(cryptoNet, null, System.currentTimeMillis() - startTime);
|
||||
CryptoNetManager.verifiedCryptoNetURL(cryptoNet, url, System.currentTimeMillis() - startTime);
|
||||
}else{
|
||||
System.out.println(" BitsharesCryptoNetVerifier Error we are not in the net current chain id " + response.result + " excepted " + CHAIN_ID);
|
||||
//TODO handle error bad chain
|
||||
|
@ -50,15 +43,8 @@ public class BitsharesCryptoNetVerifier extends CryptoNetVerifier {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
//TODO handle error
|
||||
}
|
||||
}),null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void checkURL(final String url) {
|
||||
thread.setmUrl(url); //Set the url
|
||||
thread.start(); //Run the thread connection
|
||||
}),url);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package cy.agorise.crystalwallet.network;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
|
||||
/**
|
||||
|
@ -15,14 +12,6 @@ import cy.agorise.crystalwallet.enums.CryptoNet;
|
|||
|
||||
public abstract class CryptoNetVerifier {
|
||||
|
||||
/*
|
||||
* Contains the worker connection thread
|
||||
*/
|
||||
protected WebSocketThread thread;
|
||||
|
||||
|
||||
|
||||
|
||||
static CryptoNetVerifier getNetworkVerify(CryptoNet cryptoNet){
|
||||
if(cryptoNet.getLabel().equals(CryptoNet.BITSHARES.getLabel())){
|
||||
return new BitsharesCryptoNetVerifier();
|
||||
|
@ -33,9 +22,4 @@ public abstract class CryptoNetVerifier {
|
|||
public abstract void checkURL(final String url);
|
||||
|
||||
public abstract String getChainId();
|
||||
|
||||
|
||||
public WebSocketThread getThread() {
|
||||
return thread;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package cy.agorise.crystalwallet.network;
|
|||
import android.util.Log;
|
||||
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketException;
|
||||
import com.neovisionaries.ws.client.WebSocketFactory;
|
||||
import com.neovisionaries.ws.client.WebSocketListener;
|
||||
|
||||
|
@ -33,11 +34,6 @@ public class WebSocketThread extends Thread {
|
|||
private boolean canChange = true;
|
||||
|
||||
|
||||
/*
|
||||
* Object needed for socket connection
|
||||
* */
|
||||
private WebSocketFactory factory;
|
||||
|
||||
/**
|
||||
* Basic constructor,
|
||||
*
|
||||
|
@ -47,20 +43,10 @@ public class WebSocketThread extends Thread {
|
|||
* @param url The url to connect
|
||||
*/
|
||||
public WebSocketThread(WebSocketListener webSocketListener, String url) {
|
||||
|
||||
/*
|
||||
* The listener always can be setted
|
||||
* */
|
||||
this.mWebSocketListener = webSocketListener;
|
||||
|
||||
/*
|
||||
*
|
||||
* If at this point the url is not defined, this will be set after
|
||||
* */
|
||||
if(url!=null){
|
||||
try {
|
||||
factory = new WebSocketFactory().setConnectionTimeout(5000);
|
||||
WebSocketFactory factory = new WebSocketFactory().setConnectionTimeout(5000);
|
||||
this.mUrl = url;
|
||||
this.mWebSocketListener = webSocketListener;
|
||||
this.mWebSocket = factory.createSocket(this.mUrl);
|
||||
this.mWebSocket.addListener(this.mWebSocketListener);
|
||||
} catch (IOException e) {
|
||||
|
@ -69,7 +55,6 @@ public class WebSocketThread extends Thread {
|
|||
Log.e(TAG, "NullPointerException at WebsocketWorkerThreas. Msg: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current url where the websocket will connect
|
||||
|
@ -125,28 +110,16 @@ public class WebSocketThread extends Thread {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
canChange = false;
|
||||
|
||||
// Moves the current Thread into the background
|
||||
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* If the initialization of the socket comes after
|
||||
* */
|
||||
if(factory==null){
|
||||
factory = new WebSocketFactory().setConnectionTimeout(5000);
|
||||
this.mWebSocket = factory.createSocket(this.mUrl);
|
||||
this.mWebSocket.addListener(this.mWebSocketListener);
|
||||
}
|
||||
|
||||
WebSocketThread.currentThreads.put(this.getId(),this);
|
||||
mWebSocket.connect();
|
||||
|
||||
} catch (final Exception e) {
|
||||
} catch (WebSocketException e) {
|
||||
Log.e(TAG, "WebSocketException. Msg: "+e.getMessage());
|
||||
} catch(NullPointerException e){
|
||||
Log.e(TAG, "NullPointerException. Msg: "+e.getMessage());
|
||||
}
|
||||
WebSocketThread.currentThreads.remove(this.getId());
|
||||
}
|
||||
|
@ -154,9 +127,4 @@ public class WebSocketThread extends Thread {
|
|||
public boolean isConnected(){
|
||||
return mWebSocket.isOpen();
|
||||
}
|
||||
|
||||
|
||||
public void setmUrl(String mUrl) {
|
||||
this.mUrl = mUrl;
|
||||
}
|
||||
}
|
|
@ -69,6 +69,7 @@ class BitsharesAccountNameValidation : CustomValidationField, UIValidator {
|
|||
* Remove error
|
||||
* */
|
||||
accountNameField.error = null
|
||||
accountNameField.fieldValidatorModel.setValid()
|
||||
|
||||
/*
|
||||
Validate at least min length
|
||||
|
@ -87,6 +88,7 @@ class BitsharesAccountNameValidation : CustomValidationField, UIValidator {
|
|||
* Remove error
|
||||
* */
|
||||
accountNameField.error = null
|
||||
accountNameField.fieldValidatorModel.setValid()
|
||||
|
||||
/*
|
||||
Validate at least one character
|
||||
|
@ -105,6 +107,7 @@ class BitsharesAccountNameValidation : CustomValidationField, UIValidator {
|
|||
* Remove error
|
||||
* */
|
||||
accountNameField.error = null
|
||||
accountNameField.fieldValidatorModel.setValid()
|
||||
|
||||
/*
|
||||
Validate at least one number for the account string
|
||||
|
@ -117,12 +120,14 @@ class BitsharesAccountNameValidation : CustomValidationField, UIValidator {
|
|||
result = false
|
||||
accountNameField.fieldValidatorModel.setInvalid()
|
||||
accountNameField.fieldValidatorModel.message = this.accountNameField.resources.getString(R.string.create_account_window_err_at_least_one_number)
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Remove error
|
||||
* */
|
||||
accountNameField.error = null
|
||||
accountNameField.fieldValidatorModel.setValid()
|
||||
|
||||
|
||||
/*
|
||||
|
@ -136,12 +141,14 @@ class BitsharesAccountNameValidation : CustomValidationField, UIValidator {
|
|||
result = false
|
||||
accountNameField.fieldValidatorModel.setInvalid()
|
||||
accountNameField.fieldValidatorModel.message = this.accountNameField.resources.getString(R.string.create_account_window_err_at_least_one_script)
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Remove error
|
||||
* */
|
||||
accountNameField.error = null
|
||||
accountNameField.fieldValidatorModel.setValid()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -162,47 +169,12 @@ class BitsharesAccountNameValidation : CustomValidationField, UIValidator {
|
|||
} else {
|
||||
|
||||
/*
|
||||
* Show the dialog for connection with the server
|
||||
* */
|
||||
val creatingAccountMaterialDialog = CrystalDialog(activity)
|
||||
creatingAccountMaterialDialog.setText(activity.resources.getString(R.string.window_create_seed_Server_validation))
|
||||
creatingAccountMaterialDialog.build()
|
||||
creatingAccountMaterialDialog.show()
|
||||
|
||||
val request = ValidateExistBitsharesAccountRequest(newValue)
|
||||
request.setListener {
|
||||
|
||||
/*
|
||||
* Dismiss the dialog of loading
|
||||
* */
|
||||
creatingAccountMaterialDialog.dismiss()
|
||||
|
||||
if (request.accountExists) {
|
||||
|
||||
/*
|
||||
* The account exists and is not valid
|
||||
* */
|
||||
accountNameField.fieldValidatorModel.setInvalid()
|
||||
accountNameField.fieldValidatorModel.message = accountNameField.resources.getString(R.string.account_name_already_exist)
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Passed all validations
|
||||
* */
|
||||
accountNameField.fieldValidatorModel.setValid()
|
||||
|
||||
/*
|
||||
* Deliver the response
|
||||
* Deliver result
|
||||
* */
|
||||
if (uiValidatorListener != null) {
|
||||
uiValidatorListener.onValidationSucceeded(globalCustomValidationField)
|
||||
uiValidatorListener.onValidationSucceeded(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
CryptoNetInfoRequests.getInstance().addRequest(request)
|
||||
|
||||
}
|
||||
/*
|
||||
* Passed initial validations, next final validations
|
||||
* */
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
package cy.agorise.crystalwallet.views.natives.spinners
|
||||
|
||||
import android.R
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountRequest
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.validationfields.ValidationField
|
||||
import cy.agorise.crystalwallet.views.CryptoNetAccountAdapter
|
||||
|
||||
class CryptoNetAccountsSpinner : InternalMaterialSpinner {
|
||||
|
||||
/*
|
||||
* Contains the list of accounts
|
||||
* */
|
||||
private var cryptoNetAccounts: MutableList<CryptoNetAccount>? = null
|
||||
|
||||
/*
|
||||
* Contains the current adapter
|
||||
* */
|
||||
private var fromSpinnerAdapter:CryptoNetAccountAdapter? = null
|
||||
|
||||
/*
|
||||
* Listeners
|
||||
* */
|
||||
private var onValidationField:OnValidationFailed? = null
|
||||
private var onValidationSucceeded:OnValidationSucceeded? = null
|
||||
private var onAccountNotExists:OnAccountNotExists? = null
|
||||
private var onItemSelectedListener:OnItemSelectedListener? = null
|
||||
private var onAccountExists:OnAccountExists? = null
|
||||
|
||||
/*
|
||||
* Current selected account
|
||||
* */
|
||||
private var cryptoNetAccount:CryptoNetAccount? = null
|
||||
|
||||
|
||||
|
||||
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context,attrs){
|
||||
|
||||
/*
|
||||
* Initialy starts with the android layout
|
||||
* */
|
||||
setAndroidLayout()
|
||||
|
||||
/*
|
||||
* When the user changes the item selection save the model
|
||||
* */
|
||||
setOnItemSelectedListener(OnItemSelectedListener<CryptoNetAccount> { view, position, id, item ->
|
||||
|
||||
/*
|
||||
* Save the current model
|
||||
* */
|
||||
cryptoNetAccount = cryptoNetAccounts?.get(position)
|
||||
|
||||
/*
|
||||
* Deliver response
|
||||
* */
|
||||
if(onItemSelectedListener != null){
|
||||
onItemSelectedListener?.onItemSelectedListener(cryptoNetAccount!!)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current selected cryptonetaccount
|
||||
* */
|
||||
fun getCryptoNetAccountSelected() : CryptoNetAccount{
|
||||
return this.cryptoNetAccount!!
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the current layoutview
|
||||
* */
|
||||
fun setLayout(layout:Int){
|
||||
this.layout = layout
|
||||
}
|
||||
|
||||
/*
|
||||
* Init the spinner, before call this method, this list of items should be set
|
||||
* */
|
||||
fun initCryptoNetAccountAdapter(){
|
||||
|
||||
fromSpinnerAdapter = CryptoNetAccountAdapter(context, this.layout!!, cryptoNetAccounts)
|
||||
setAdapter(fromSpinnerAdapter!!)
|
||||
}
|
||||
|
||||
|
||||
fun setCryptoAccountItems(cryptoNetAccounts:MutableList<CryptoNetAccount>){
|
||||
this.cryptoNetAccounts = cryptoNetAccounts
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate if the "selected" account exists
|
||||
* */
|
||||
fun validateExistBitsharesAccountRequest(){
|
||||
|
||||
if(cryptoNetAccount != null){
|
||||
|
||||
val request = ValidateExistBitsharesAccountRequest(cryptoNetAccount?.name)
|
||||
request.setListener {
|
||||
if (!request.accountExists) {
|
||||
if(onAccountNotExists != null){
|
||||
onAccountNotExists?.onAccountNotExists(this_!!)
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if(onAccountExists != null){
|
||||
onAccountExists?.onAccountExists(this_!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
CryptoNetInfoRequests.getInstance().addRequest(request)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Listener for validations
|
||||
* */
|
||||
fun onValidationFailed(onValidationField:OnValidationFailed){
|
||||
this.onValidationField = onValidationField
|
||||
}
|
||||
fun onValidationSucceeded(onValidationSucceeded: OnValidationSucceeded){
|
||||
this.onValidationSucceeded = onValidationSucceeded
|
||||
}
|
||||
fun onAccountNotExists(onAccountNotExists: OnAccountNotExists){
|
||||
this.onAccountNotExists = onAccountNotExists
|
||||
}
|
||||
fun onItemSelectedListener(onItemSelectedListener: OnItemSelectedListener){
|
||||
this.onItemSelectedListener = onItemSelectedListener
|
||||
}
|
||||
fun onAccountExists(onAccountExists: OnAccountExists){
|
||||
this.onAccountExists = onAccountExists
|
||||
}
|
||||
/*
|
||||
* End of Listener for validations
|
||||
* */
|
||||
|
||||
/*
|
||||
* Add the items list to the spinner
|
||||
* */
|
||||
fun getCryptoAccountsList() : List<CryptoNetAccount>{
|
||||
return this.cryptoNetAccounts!!
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interface for validation failed
|
||||
* */
|
||||
interface OnAccountNotExists{
|
||||
fun onAccountNotExists(field: View)
|
||||
}
|
||||
interface OnAccountExists{
|
||||
fun onAccountExists(field: View)
|
||||
}
|
||||
interface OnItemSelectedListener{
|
||||
fun onItemSelectedListener(cryptoNetAccount: CryptoNetAccount)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package cy.agorise.crystalwallet.views.natives.spinners
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import com.jaredrummler.materialspinner.MaterialSpinner
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.UIValidatorListener
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.validationfields.ValidationField
|
||||
|
||||
open class InternalMaterialSpinner : MaterialSpinner {
|
||||
|
||||
/*
|
||||
* Contains the current layout for the rows
|
||||
* */
|
||||
protected var layout:Int? = null
|
||||
|
||||
/*
|
||||
* Listeners
|
||||
* */
|
||||
private var onItemNotSelected: OnItemNotSelected? = null
|
||||
|
||||
/*
|
||||
* Contains the this for interfaces
|
||||
* */
|
||||
protected var this_: View? = null
|
||||
|
||||
|
||||
|
||||
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context,attrs){
|
||||
|
||||
/*
|
||||
* Save the current this
|
||||
* */
|
||||
this_ = this
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the first item in the spinner
|
||||
* */
|
||||
fun selectFirstItem(){
|
||||
this.selectedIndex = 0
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the default android layout
|
||||
* */
|
||||
fun setAndroidLayout(){
|
||||
this.layout = android.R.layout.simple_spinner_item
|
||||
}
|
||||
|
||||
fun onItemNotSelected(onItemNotSelected:OnItemNotSelected){
|
||||
this.onItemNotSelected = onItemNotSelected
|
||||
}
|
||||
|
||||
/*
|
||||
* Validation with listener for item selected or not
|
||||
* */
|
||||
fun validateOnItemNotSelected(){
|
||||
if(this.selectedIndex == -1){
|
||||
if(onItemNotSelected != null){
|
||||
onItemNotSelected?.onItemNotSelected()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface for validation failed
|
||||
* */
|
||||
interface OnValidationFailed{
|
||||
fun onValidationFailed(field: ValidationField)
|
||||
}
|
||||
interface OnValidationSucceeded{
|
||||
fun onValidationSucceeded(field: ValidationField)
|
||||
}
|
||||
interface OnItemNotSelected{
|
||||
fun onItemNotSelected()
|
||||
}
|
||||
}
|
2
app/src/main/res/anim/cycle_7.xml
Normal file
2
app/src/main/res/anim/cycle_7.xml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:cycles="7" />
|
4
app/src/main/res/anim/shake.xml
Normal file
4
app/src/main/res/anim/shake.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<translate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fromXDelta="0" android:toXDelta="10" android:duration="1000"
|
||||
android:interpolator="@anim/cycle_7" />
|
12
app/src/main/res/drawable/square.xml
Normal file
12
app/src/main/res/drawable/square.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners
|
||||
android:radius="4dp"
|
||||
android:topRightRadius="4dp"
|
||||
android:bottomRightRadius="4dp"
|
||||
android:bottomLeftRadius="4dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#0099ff" />
|
||||
</shape>
|
|
@ -3,89 +3,86 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/white"
|
||||
android:paddingBottom="0dp"
|
||||
android:paddingLeft="0dp"
|
||||
android:paddingRight="0dp"
|
||||
android:paddingLeft="25dp"
|
||||
android:paddingRight="25dp"
|
||||
android:paddingTop="@dimen/activity_vertical_margin">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true">
|
||||
android:background="@color/white"
|
||||
android:padding="20dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvMnemonicTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignStart="@+id/linearlayout1"
|
||||
android:layout_marginTop="35dp"
|
||||
android:text="@string/window_seed_backup"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textSize="20dp"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="25dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearlayout1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/tvMnemonicTitle"
|
||||
android:layout_marginTop="35dp"
|
||||
android:background="@drawable/square"
|
||||
android:padding="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvBrainKey"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/tvMnemonicTitle"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/edittext_bg"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textColor="@color/black"
|
||||
android:layout_marginBottom="20dp"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/backup_seeed_imageview_warning"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginLeft="35dp"
|
||||
android:layout_alignTop="@+id/backup_seed_textview_leyend_backup"
|
||||
android:background="@drawable/warning" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/backup_seed_textview_leyend_backup"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="70dp"
|
||||
android:textColor="@color/send_strong_orange"
|
||||
android:layout_marginRight="70dp"
|
||||
android:text="@string/window_seed_leyend_backup"
|
||||
android:textSize="14dp"
|
||||
android:layout_below="@+id/tvBrainKey"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_below="@+id/backup_seed_textview_leyend_backup"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:weightSum="2">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnOk"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/ok"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnCopy"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/window_seed_copy"
|
||||
android:textColor="@color/black" />
|
||||
android:background="#00000000"
|
||||
android:textColor="@color/gray" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/backup_seed_textview_leyend_backup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/linearlayout1"
|
||||
android:layout_marginTop="35dp"
|
||||
android:text="@string/window_seed_leyend_backup"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnCancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/backup_seed_textview_leyend_backup"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginTop="35dp"
|
||||
android:layout_toLeftOf="@+id/btnCopy"
|
||||
android:text="@string/cancel"
|
||||
android:textColor="#0099ff"
|
||||
android:background="?android:attr/selectableItemBackground"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnCopy"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/backup_seed_textview_leyend_backup"
|
||||
android:layout_marginTop="35dp"
|
||||
android:text="@string/window_seed_copy"
|
||||
android:textColor="#0099ff"
|
||||
android:background="?android:attr/selectableItemBackground"/>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
|
||||
</android.support.v7.widget.Toolbar>
|
||||
|
||||
<android.support.design.widget.TabLayout
|
||||
<com.sjaramillo10.animatedtablayout.AnimatedTabLayout
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/transparent"
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
android:layout_marginTop="24dp"
|
||||
android:text="@string/brainkey_description"
|
||||
android:textSize="15sp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="@id/tvBinFile"
|
||||
app:layout_constraintStart_toStartOf="@id/tvBinFile"
|
||||
app:layout_constraintTop_toBottomOf="@id/btnBinFile" />
|
||||
|
@ -53,7 +52,6 @@
|
|||
android:text="@string/view_and_copy"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintStart_toStartOf="@id/btnBinFile"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvBrainkey" />
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
|
@ -13,12 +14,10 @@
|
|||
<View
|
||||
android:id="@+id/topView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="119dp"
|
||||
android:background="@drawable/send_transaction_top_view"
|
||||
android:layout_height="120dp"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginTop="0dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
@ -228,16 +227,27 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/viewSend" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnCancel"
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="600dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:text="@string/cancel_capital"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:padding="5dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnCancel"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="26dp"
|
||||
android:background="@drawable/ic_close"
|
||||
android:text=""
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
|
|
Loading…
Reference in a new issue