JunZhang
5 years ago
committed by
GitHub
63 changed files with 3178 additions and 210 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,5 @@ |
|||
package com.cobo.cold.ui.fragment.main.electrum; |
|||
|
|||
public interface Callback { |
|||
void onClick(String file); |
|||
} |
@ -0,0 +1,97 @@ |
|||
/* |
|||
* Copyright (c) 2020 Cobo |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation, either version 3 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* in the file COPYING. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
package com.cobo.cold.ui.fragment.main.electrum; |
|||
|
|||
import android.os.Bundle; |
|||
import android.view.Gravity; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
|
|||
import androidx.databinding.DataBindingUtil; |
|||
import androidx.lifecycle.ViewModelProviders; |
|||
|
|||
import com.cobo.coinlib.utils.Base43; |
|||
import com.cobo.cold.R; |
|||
import com.cobo.cold.databinding.BroadcastElectrumTxFragmentBinding; |
|||
import com.cobo.cold.databinding.CommonModalBinding; |
|||
import com.cobo.cold.db.entity.TxEntity; |
|||
import com.cobo.cold.ui.fragment.BaseFragment; |
|||
import com.cobo.cold.ui.modal.ModalDialog; |
|||
import com.cobo.cold.viewmodel.CoinListViewModel; |
|||
|
|||
import org.spongycastle.util.encoders.Hex; |
|||
|
|||
import java.util.Objects; |
|||
|
|||
import static com.cobo.cold.ui.fragment.main.electrum.ElectrumTxConfirmFragment.showExportTxnDialog; |
|||
|
|||
public class ElectrumBroadcastTxFragment extends BaseFragment<BroadcastElectrumTxFragmentBinding> { |
|||
|
|||
public static final String KEY_TXID = "txId"; |
|||
private final View.OnClickListener goHome = v -> navigate(R.id.action_to_home); |
|||
private TxEntity txEntity; |
|||
|
|||
@Override |
|||
protected int setView() { |
|||
return R.layout.broadcast_electrum_tx_fragment; |
|||
} |
|||
|
|||
@Override |
|||
protected void init(View view) { |
|||
Bundle data = Objects.requireNonNull(getArguments()); |
|||
mBinding.toolbar.setNavigationOnClickListener(goHome); |
|||
mBinding.complete.setOnClickListener(goHome); |
|||
CoinListViewModel viewModel = ViewModelProviders.of(mActivity).get(CoinListViewModel.class); |
|||
viewModel.loadTx(data.getString(KEY_TXID)).observe(this, txEntity -> { |
|||
this.txEntity = txEntity; |
|||
mBinding.setCoinCode(txEntity.getCoinCode()); |
|||
String txString = getSignTxString(txEntity); |
|||
mBinding.qrcodeLayout.qrcode.setData(txString); |
|||
}); |
|||
mBinding.hint.setOnClickListener(v -> { |
|||
if (txEntity != null) { |
|||
showExportTxnDialog(mActivity, txEntity.getTxId(), txEntity.getSignedHex()); |
|||
} |
|||
}); |
|||
mBinding.info.setOnClickListener(v -> showElectrumInfo()); |
|||
} |
|||
|
|||
private void showElectrumInfo() { |
|||
ModalDialog modalDialog = ModalDialog.newInstance(); |
|||
CommonModalBinding binding = DataBindingUtil.inflate( |
|||
LayoutInflater.from(mActivity), R.layout.common_modal, |
|||
null, false); |
|||
binding.title.setText(R.string.electrum_broadcast_guide); |
|||
binding.subTitle.setText(R.string.electrum_broadcast_action_guide); |
|||
binding.subTitle.setGravity(Gravity.START); |
|||
binding.close.setVisibility(View.GONE); |
|||
binding.confirm.setText(R.string.know); |
|||
binding.confirm.setOnClickListener(vv -> modalDialog.dismiss()); |
|||
modalDialog.setBinding(binding); |
|||
modalDialog.show(mActivity.getSupportFragmentManager(), ""); |
|||
} |
|||
|
|||
@Override |
|||
protected void initData(Bundle savedInstanceState) { |
|||
|
|||
} |
|||
|
|||
private String getSignTxString(TxEntity txEntity) { |
|||
return Base43.encode(Hex.decode(txEntity.getSignedHex())); |
|||
} |
|||
} |
@ -0,0 +1,107 @@ |
|||
/* |
|||
* Copyright (c) 2020 Cobo |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation, either version 3 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* in the file COPYING. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
package com.cobo.cold.ui.fragment.main.electrum; |
|||
|
|||
import android.os.Bundle; |
|||
import android.text.TextUtils; |
|||
import android.view.Gravity; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
|
|||
import androidx.databinding.DataBindingUtil; |
|||
import androidx.lifecycle.ViewModelProviders; |
|||
|
|||
import com.cobo.cold.R; |
|||
import com.cobo.cold.databinding.CommonModalBinding; |
|||
import com.cobo.cold.databinding.ElectrumExportBinding; |
|||
import com.cobo.cold.databinding.ExportSdcardModalBinding; |
|||
import com.cobo.cold.ui.fragment.BaseFragment; |
|||
import com.cobo.cold.ui.modal.ModalDialog; |
|||
import com.cobo.cold.update.utils.Storage; |
|||
import com.cobo.cold.viewmodel.ElectrumViewModel; |
|||
|
|||
import static com.cobo.cold.viewmodel.ElectrumViewModel.exportSuccess; |
|||
import static com.cobo.cold.viewmodel.ElectrumViewModel.showNoSdcardModal; |
|||
import static com.cobo.cold.viewmodel.ElectrumViewModel.writeToSdcard; |
|||
|
|||
public class ElectrumExportFragment extends BaseFragment<ElectrumExportBinding> { |
|||
|
|||
private static final String EXTEND_PUB_FILE_NAME = "CV-P2SH-P2WPKH-pubkey.txt"; |
|||
private String exPub; |
|||
|
|||
@Override |
|||
protected int setView() { |
|||
return R.layout.electrum_export; |
|||
} |
|||
|
|||
@Override |
|||
protected void init(View view) { |
|||
mBinding.toolbar.setNavigationOnClickListener(v -> navigateUp()); |
|||
ElectrumViewModel viewModel = ViewModelProviders.of(this).get(ElectrumViewModel.class); |
|||
viewModel.getExPub().observe(this, s -> { |
|||
if (!TextUtils.isEmpty(s)) { |
|||
exPub = s; |
|||
mBinding.qrcode.setData(s); |
|||
mBinding.expub.setText(s); |
|||
} |
|||
}); |
|||
mBinding.info.setOnClickListener(v -> showElectrumInfo()); |
|||
mBinding.exportToSdcard.setOnClickListener(v -> { |
|||
Storage storage = Storage.createByEnvironment(mActivity); |
|||
if (storage == null || storage.getExternalDir() == null) { |
|||
showNoSdcardModal(mActivity); |
|||
} else { |
|||
ModalDialog modalDialog = ModalDialog.newInstance(); |
|||
ExportSdcardModalBinding binding = DataBindingUtil.inflate(LayoutInflater.from(mActivity), |
|||
R.layout.export_sdcard_modal, null, false); |
|||
binding.title.setText(R.string.export_xpub_text_file); |
|||
binding.fileName.setText(EXTEND_PUB_FILE_NAME); |
|||
binding.actionHint.setText(R.string.electrum_import_xpub_action); |
|||
binding.cancel.setOnClickListener(vv -> modalDialog.dismiss()); |
|||
binding.confirm.setOnClickListener(vv -> { |
|||
modalDialog.dismiss(); |
|||
if (writeToSdcard(storage, exPub, EXTEND_PUB_FILE_NAME)) { |
|||
exportSuccess(mActivity); |
|||
} |
|||
}); |
|||
modalDialog.setBinding(binding); |
|||
modalDialog.show(mActivity.getSupportFragmentManager(), ""); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private void showElectrumInfo() { |
|||
ModalDialog modalDialog = ModalDialog.newInstance(); |
|||
CommonModalBinding binding = DataBindingUtil.inflate( |
|||
LayoutInflater.from(mActivity), R.layout.common_modal, |
|||
null, false); |
|||
binding.title.setText(R.string.electrum_import_xpub_guide_title); |
|||
binding.subTitle.setText(R.string.electrum_import_xpub_action_guide); |
|||
binding.subTitle.setGravity(Gravity.START); |
|||
binding.close.setVisibility(View.GONE); |
|||
binding.confirm.setText(R.string.know); |
|||
binding.confirm.setOnClickListener(vv -> modalDialog.dismiss()); |
|||
modalDialog.setBinding(binding); |
|||
modalDialog.show(mActivity.getSupportFragmentManager(), ""); |
|||
} |
|||
|
|||
@Override |
|||
protected void initData(Bundle savedInstanceState) { |
|||
|
|||
} |
|||
} |
@ -0,0 +1,44 @@ |
|||
/* |
|||
* Copyright (c) 2020 Cobo |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation, either version 3 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* in the file COPYING. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
package com.cobo.cold.ui.fragment.main.electrum; |
|||
|
|||
import android.os.Bundle; |
|||
import android.view.View; |
|||
|
|||
import com.cobo.cold.R; |
|||
import com.cobo.cold.databinding.ElectrumExportGuideBinding; |
|||
import com.cobo.cold.ui.fragment.BaseFragment; |
|||
|
|||
public class ElectrumGuideFragment extends BaseFragment<ElectrumExportGuideBinding> { |
|||
|
|||
@Override |
|||
protected int setView() { |
|||
return R.layout.electrum_export_guide; |
|||
} |
|||
|
|||
@Override |
|||
protected void init(View view) { |
|||
mBinding.toolbar.setNavigationOnClickListener(v -> navigateUp()); |
|||
mBinding.export.setOnClickListener(v -> navigate(R.id.export_electrum_ypub)); |
|||
} |
|||
|
|||
@Override |
|||
protected void initData(Bundle savedInstanceState) { |
|||
|
|||
} |
|||
} |
@ -0,0 +1,342 @@ |
|||
/* |
|||
* Copyright (c) 2020 Cobo |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation, either version 3 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* in the file COPYING. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
package com.cobo.cold.ui.fragment.main.electrum; |
|||
|
|||
import android.os.Bundle; |
|||
import android.os.Handler; |
|||
import android.text.Spannable; |
|||
import android.text.SpannableStringBuilder; |
|||
import android.text.style.ForegroundColorSpan; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
|
|||
import androidx.appcompat.app.AppCompatActivity; |
|||
import androidx.databinding.DataBindingUtil; |
|||
import androidx.lifecycle.ViewModelProviders; |
|||
import androidx.navigation.Navigation; |
|||
|
|||
import com.cobo.coinlib.coins.BTC.Electrum.ElectrumTx; |
|||
import com.cobo.coinlib.utils.Base43; |
|||
import com.cobo.cold.R; |
|||
import com.cobo.cold.Utilities; |
|||
import com.cobo.cold.config.FeatureFlags; |
|||
import com.cobo.cold.databinding.ElectrumTxConfirmFragmentBinding; |
|||
import com.cobo.cold.databinding.ExportSdcardModalBinding; |
|||
import com.cobo.cold.databinding.ProgressModalBinding; |
|||
import com.cobo.cold.db.entity.TxEntity; |
|||
import com.cobo.cold.encryptioncore.utils.ByteFormatter; |
|||
import com.cobo.cold.ui.fragment.BaseFragment; |
|||
import com.cobo.cold.ui.fragment.main.TxConfirmFragment; |
|||
import com.cobo.cold.ui.modal.ModalDialog; |
|||
import com.cobo.cold.ui.modal.ProgressModalDialog; |
|||
import com.cobo.cold.ui.modal.SigningDialog; |
|||
import com.cobo.cold.ui.views.AuthenticateModal; |
|||
import com.cobo.cold.update.utils.Storage; |
|||
import com.cobo.cold.util.KeyStoreUtil; |
|||
import com.cobo.cold.viewmodel.TxConfirmViewModel; |
|||
|
|||
import org.json.JSONArray; |
|||
import org.json.JSONException; |
|||
import org.json.JSONObject; |
|||
import org.spongycastle.util.encoders.Hex; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.Objects; |
|||
|
|||
import static com.cobo.cold.ui.fragment.Constants.KEY_NAV_ID; |
|||
import static com.cobo.cold.ui.fragment.main.BroadcastTxFragment.KEY_TXID; |
|||
import static com.cobo.cold.viewmodel.ElectrumViewModel.exportSuccess; |
|||
import static com.cobo.cold.viewmodel.ElectrumViewModel.hasSdcard; |
|||
import static com.cobo.cold.viewmodel.ElectrumViewModel.showNoSdcardModal; |
|||
import static com.cobo.cold.viewmodel.ElectrumViewModel.writeToSdcard; |
|||
|
|||
public class ElectrumTxConfirmFragment extends BaseFragment<ElectrumTxConfirmFragmentBinding> { |
|||
|
|||
private final Runnable forgetPassword = () -> { |
|||
Bundle data = new Bundle(); |
|||
data.putInt(KEY_NAV_ID, R.id.action_to_setPasswordFragment1); |
|||
Navigation.findNavController(Objects.requireNonNull(getView())) |
|||
.navigate(R.id.action_to_verifyMnemonic, data); |
|||
}; |
|||
private TxConfirmViewModel viewModel; |
|||
private SigningDialog signingDialog; |
|||
private TxEntity txEntity; |
|||
private ModalDialog addingAddressDialog; |
|||
private String txnData; |
|||
|
|||
public static void showExportTxnDialog(AppCompatActivity activity, String txId, String hex) { |
|||
ModalDialog modalDialog = ModalDialog.newInstance(); |
|||
ExportSdcardModalBinding binding = DataBindingUtil.inflate(LayoutInflater.from(activity), |
|||
R.layout.export_sdcard_modal, null, false); |
|||
String fileName = txId.substring(0, 5) + "-signed.txn"; |
|||
binding.title.setText(R.string.export_signed_txn); |
|||
binding.fileName.setText(fileName); |
|||
binding.actionHint.setText(R.string.electrum_import_signed_txn); |
|||
binding.cancel.setOnClickListener(vv -> modalDialog.dismiss()); |
|||
binding.confirm.setOnClickListener(vv -> { |
|||
modalDialog.dismiss(); |
|||
if (hasSdcard(activity)) { |
|||
Storage storage = Storage.createByEnvironment(activity); |
|||
boolean result = writeToSdcard(storage, generateElectrumTxn(hex), fileName); |
|||
if (result) { |
|||
exportSuccess(activity); |
|||
} |
|||
} else { |
|||
showNoSdcardModal(activity); |
|||
} |
|||
}); |
|||
modalDialog.setBinding(binding); |
|||
modalDialog.show(activity.getSupportFragmentManager(), ""); |
|||
} |
|||
|
|||
private static String generateElectrumTxn(String hex) { |
|||
JSONObject txn = new JSONObject(); |
|||
try { |
|||
txn.put("hex", hex); |
|||
txn.put("complete", true); |
|||
txn.put("final", ElectrumTx.isFinal(hex)); |
|||
return txn.toString(); |
|||
} catch (JSONException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
@Override |
|||
protected int setView() { |
|||
return R.layout.electrum_tx_confirm_fragment; |
|||
} |
|||
|
|||
@Override |
|||
protected void init(View view) { |
|||
Bundle bundle = Objects.requireNonNull(getArguments()); |
|||
mBinding.toolbar.setNavigationOnClickListener(v -> navigateUp()); |
|||
mBinding.txDetail.txIdInfo.setVisibility(View.GONE); |
|||
mBinding.txDetail.qrcodeLayout.qrcode.setVisibility(View.GONE); |
|||
mBinding.txDetail.export.setVisibility(View.GONE); |
|||
txnData = bundle.getString("txn"); |
|||
viewModel = ViewModelProviders.of(this).get(TxConfirmViewModel.class); |
|||
mBinding.setViewModel(viewModel); |
|||
subscribeTxEntityState(); |
|||
|
|||
mBinding.sign.setOnClickListener(v -> handleSign()); |
|||
|
|||
} |
|||
|
|||
private void handleSign() { |
|||
boolean fingerprintSignEnable = Utilities.isFingerprintSignEnable(mActivity); |
|||
if (txEntity != null) { |
|||
if (FeatureFlags.ENABLE_WHITE_LIST) { |
|||
if (isAddressInWhiteList()) { |
|||
AuthenticateModal.show(mActivity, |
|||
getString(R.string.password_modal_title), |
|||
"", |
|||
fingerprintSignEnable, |
|||
signWithVerifyInfo(), forgetPassword); |
|||
} else { |
|||
Utilities.alert(mActivity, getString(R.string.hint), |
|||
getString(R.string.not_in_whitelist_reject), |
|||
getString(R.string.confirm), |
|||
() -> navigate(R.id.action_to_home)); |
|||
} |
|||
|
|||
} else { |
|||
AuthenticateModal.show(mActivity, |
|||
getString(R.string.password_modal_title), |
|||
"", |
|||
fingerprintSignEnable, |
|||
signWithVerifyInfo(), forgetPassword); |
|||
} |
|||
} else { |
|||
navigate(R.id.action_to_home); |
|||
} |
|||
} |
|||
|
|||
private AuthenticateModal.OnVerify signWithVerifyInfo() { |
|||
return token -> { |
|||
viewModel.setToken(token); |
|||
viewModel.handleSign(); |
|||
subscribeSignState(); |
|||
}; |
|||
} |
|||
|
|||
private void subscribeTxEntityState() { |
|||
ProgressModalDialog dialog = new ProgressModalDialog(); |
|||
dialog.show(mActivity.getSupportFragmentManager(), ""); |
|||
viewModel.parseTxnData(txnData); |
|||
viewModel.getObservableTx().observe(this, txEntity -> { |
|||
if (txEntity != null) { |
|||
dialog.dismiss(); |
|||
this.txEntity = txEntity; |
|||
mBinding.setTx(txEntity); |
|||
refreshAmount(); |
|||
refreshFromList(); |
|||
refreshReceiveList(); |
|||
} |
|||
}); |
|||
|
|||
viewModel.getAddingAddressState().observe(this, b -> { |
|||
if (b) { |
|||
addingAddressDialog = ModalDialog.newInstance(); |
|||
ProgressModalBinding binding = DataBindingUtil.inflate(LayoutInflater.from(mActivity), |
|||
R.layout.progress_modal, null, false); |
|||
binding.text.setText(R.string.sync_in_progress); |
|||
binding.text.setVisibility(View.VISIBLE); |
|||
addingAddressDialog.setBinding(binding); |
|||
addingAddressDialog.show(mActivity.getSupportFragmentManager(), ""); |
|||
} else { |
|||
if (addingAddressDialog != null) { |
|||
addingAddressDialog.dismiss(); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
viewModel.parseTxException().observe(this, ex -> { |
|||
if (ex != null) { |
|||
ex.printStackTrace(); |
|||
dialog.dismiss(); |
|||
ModalDialog.showCommonModal(mActivity, |
|||
getString(R.string.electrum_decode_txn_fail), |
|||
getString(R.string.incorrect_tx_data), |
|||
getString(R.string.confirm), |
|||
null); |
|||
navigateUp(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private void refreshAmount() { |
|||
SpannableStringBuilder style = new SpannableStringBuilder(txEntity.getAmount()); |
|||
style.setSpan(new ForegroundColorSpan(mActivity.getColor(R.color.colorAccent)), |
|||
0, txEntity.getAmount().indexOf(" "), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
|||
mBinding.txDetail.amount.setText(style); |
|||
} |
|||
|
|||
private void refreshReceiveList() { |
|||
String to = txEntity.getTo(); |
|||
List<TxConfirmFragment.TransactionItem> items = new ArrayList<>(); |
|||
try { |
|||
JSONArray outputs = new JSONArray(to); |
|||
for (int i = 0; i < outputs.length(); i++) { |
|||
items.add(new TxConfirmFragment.TransactionItem(i, |
|||
outputs.getJSONObject(i).getLong("value"), |
|||
outputs.getJSONObject(i).getString("address") |
|||
)); |
|||
} |
|||
} catch (JSONException e) { |
|||
return; |
|||
} |
|||
TxConfirmFragment.TransactionItemAdapter adapter |
|||
= new TxConfirmFragment.TransactionItemAdapter(mActivity, |
|||
TxConfirmFragment.TransactionItem.ItemType.OUTPUT); |
|||
adapter.setItems(items); |
|||
mBinding.txDetail.toList.setVisibility(View.VISIBLE); |
|||
mBinding.txDetail.toList.setAdapter(adapter); |
|||
} |
|||
|
|||
private void refreshFromList() { |
|||
String to = txEntity.getFrom(); |
|||
List<TxConfirmFragment.TransactionItem> items = new ArrayList<>(); |
|||
try { |
|||
JSONArray outputs = new JSONArray(to); |
|||
for (int i = 0; i < outputs.length(); i++) { |
|||
JSONObject out = outputs.getJSONObject(i); |
|||
items.add(new TxConfirmFragment.TransactionItem(i, |
|||
out.getLong("value"), |
|||
out.getString("address"))); |
|||
} |
|||
} catch (JSONException e) { |
|||
return; |
|||
} |
|||
TxConfirmFragment.TransactionItemAdapter adapter |
|||
= new TxConfirmFragment.TransactionItemAdapter(mActivity, |
|||
TxConfirmFragment.TransactionItem.ItemType.INPUT); |
|||
adapter.setItems(items); |
|||
mBinding.txDetail.fromList.setVisibility(View.VISIBLE); |
|||
mBinding.txDetail.fromList.setAdapter(adapter); |
|||
} |
|||
|
|||
private void subscribeSignState() { |
|||
viewModel.getSignState().observe(this, s -> { |
|||
if (TxConfirmViewModel.STATE_SIGNING.equals(s)) { |
|||
signingDialog = SigningDialog.newInstance(); |
|||
signingDialog.show(mActivity.getSupportFragmentManager(), ""); |
|||
} else if (TxConfirmViewModel.STATE_SIGN_SUCCESS.equals(s)) { |
|||
if (signingDialog != null) { |
|||
signingDialog.setState(SigningDialog.STATE_SUCCESS); |
|||
} |
|||
new Handler().postDelayed(() -> { |
|||
if (signingDialog != null) { |
|||
signingDialog.dismiss(); |
|||
} |
|||
signingDialog = null; |
|||
onSignSuccess(); |
|||
}, 500); |
|||
} else if (TxConfirmViewModel.STATE_SIGN_FAIL.equals(s)) { |
|||
if (signingDialog == null) { |
|||
signingDialog = SigningDialog.newInstance(); |
|||
signingDialog.show(mActivity.getSupportFragmentManager(), ""); |
|||
} |
|||
new Handler().postDelayed(() -> signingDialog.setState(SigningDialog.STATE_FAIL), 1000); |
|||
new Handler().postDelayed(() -> { |
|||
if (signingDialog != null) { |
|||
signingDialog.dismiss(); |
|||
} |
|||
signingDialog = null; |
|||
viewModel.getSignState().removeObservers(this); |
|||
}, 2000); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private void onSignSuccess() { |
|||
handleTxnSignSuccess(); |
|||
viewModel.getSignState().removeObservers(this); |
|||
} |
|||
|
|||
private void handleTxnSignSuccess() { |
|||
String hex = viewModel.getTxHex(); |
|||
String base43 = Base43.encode(Hex.decode(hex)); |
|||
if (base43.length() <= 1000) { |
|||
String txId = viewModel.getTxId(); |
|||
Bundle data = new Bundle(); |
|||
data.putString(KEY_TXID, txId); |
|||
navigate(R.id.action_to_broadcastElectrumTxFragment, data); |
|||
} else { |
|||
showExportTxnDialog(mActivity, viewModel.getTxId(), viewModel.getTxHex()); |
|||
} |
|||
} |
|||
|
|||
private boolean isAddressInWhiteList() { |
|||
String to = txEntity.getTo(); |
|||
String encryptedAddress = ByteFormatter.bytes2hex( |
|||
new KeyStoreUtil().encrypt(to.getBytes(StandardCharsets.UTF_8))); |
|||
return viewModel.isAddressInWhiteList(encryptedAddress); |
|||
} |
|||
|
|||
@Override |
|||
protected void initData(Bundle savedInstanceState) { |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
|
@ -0,0 +1,140 @@ |
|||
/* |
|||
* Copyright (c) 2020 Cobo |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation, either version 3 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* in the file COPYING. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
package com.cobo.cold.ui.fragment.main.electrum; |
|||
|
|||
import android.os.Bundle; |
|||
import android.os.Handler; |
|||
import android.text.Spannable; |
|||
import android.text.SpannableStringBuilder; |
|||
import android.text.style.ForegroundColorSpan; |
|||
import android.view.View; |
|||
|
|||
import androidx.lifecycle.ViewModelProviders; |
|||
|
|||
import com.cobo.coinlib.utils.Base43; |
|||
import com.cobo.cold.R; |
|||
import com.cobo.cold.databinding.ElectrumTxBinding; |
|||
import com.cobo.cold.db.entity.TxEntity; |
|||
import com.cobo.cold.ui.fragment.BaseFragment; |
|||
import com.cobo.cold.ui.fragment.main.TxConfirmFragment; |
|||
import com.cobo.cold.viewmodel.CoinListViewModel; |
|||
|
|||
import org.json.JSONArray; |
|||
import org.json.JSONException; |
|||
import org.json.JSONObject; |
|||
import org.spongycastle.util.encoders.Hex; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.Objects; |
|||
|
|||
import static com.cobo.cold.ui.fragment.main.electrum.ElectrumTxConfirmFragment.showExportTxnDialog; |
|||
|
|||
|
|||
public class ElectrumTxFragment extends BaseFragment<ElectrumTxBinding> { |
|||
|
|||
public static final String KEY_TX_ID = "txid"; |
|||
private TxEntity txEntity; |
|||
|
|||
@Override |
|||
protected int setView() { |
|||
return R.layout.electrum_tx; |
|||
} |
|||
|
|||
@Override |
|||
protected void init(View view) { |
|||
Bundle data = Objects.requireNonNull(getArguments()); |
|||
mBinding.toolbar.setNavigationOnClickListener(v -> navigateUp()); |
|||
CoinListViewModel viewModel = ViewModelProviders.of(mActivity).get(CoinListViewModel.class); |
|||
viewModel.loadTx(data.getString(KEY_TX_ID)).observe(this, txEntity -> { |
|||
mBinding.setTx(txEntity); |
|||
this.txEntity = txEntity; |
|||
String signTx = getSignTxString(txEntity); |
|||
if (signTx.length() <= 1000) { |
|||
new Handler().postDelayed(() -> mBinding.txDetail.qrcodeLayout.qrcode.setData(signTx), 500); |
|||
} else { |
|||
mBinding.txDetail.qrcodeLayout.qrcode.setVisibility(View.GONE); |
|||
} |
|||
refreshAmount(); |
|||
refreshFromList(); |
|||
refreshReceiveList(); |
|||
mBinding.txDetail.exportToSdcard.setOnClickListener(v -> { |
|||
showExportTxnDialog(mActivity, txEntity.getTxId(), txEntity.getSignedHex()); |
|||
}); |
|||
}); |
|||
|
|||
} |
|||
|
|||
private void refreshFromList() { |
|||
String from = txEntity.getFrom(); |
|||
List<TxConfirmFragment.TransactionItem> items = new ArrayList<>(); |
|||
try { |
|||
JSONArray outputs = new JSONArray(from); |
|||
for (int i = 0; i < outputs.length(); i++) { |
|||
JSONObject out = outputs.getJSONObject(i); |
|||
items.add(new TxConfirmFragment.TransactionItem(i, |
|||
out.getLong("value"), out.getString("address"))); |
|||
} |
|||
} catch (JSONException e) { |
|||
return; |
|||
} |
|||
TxConfirmFragment.TransactionItemAdapter adapter |
|||
= new TxConfirmFragment.TransactionItemAdapter(mActivity, |
|||
TxConfirmFragment.TransactionItem.ItemType.INPUT); |
|||
adapter.setItems(items); |
|||
mBinding.txDetail.fromList.setAdapter(adapter); |
|||
} |
|||
|
|||
private void refreshAmount() { |
|||
SpannableStringBuilder style = new SpannableStringBuilder(txEntity.getAmount()); |
|||
style.setSpan(new ForegroundColorSpan(mActivity.getColor(R.color.colorAccent)), |
|||
0, txEntity.getAmount().indexOf(" "), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
|||
mBinding.txDetail.amount.setText(style); |
|||
} |
|||
|
|||
private void refreshReceiveList() { |
|||
String to = txEntity.getTo(); |
|||
List<TxConfirmFragment.TransactionItem> items = new ArrayList<>(); |
|||
try { |
|||
JSONArray outputs = new JSONArray(to); |
|||
for (int i = 0; i < outputs.length(); i++) { |
|||
items.add(new TxConfirmFragment.TransactionItem(i, |
|||
outputs.getJSONObject(i).getLong("value"), |
|||
outputs.getJSONObject(i).getString("address") |
|||
)); |
|||
} |
|||
} catch (JSONException e) { |
|||
return; |
|||
} |
|||
TxConfirmFragment.TransactionItemAdapter adapter = |
|||
new TxConfirmFragment.TransactionItemAdapter(mActivity, TxConfirmFragment.TransactionItem.ItemType.OUTPUT); |
|||
adapter.setItems(items); |
|||
mBinding.txDetail.toList.setAdapter(adapter); |
|||
} |
|||
|
|||
@Override |
|||
protected void initData(Bundle savedInstanceState) { |
|||
|
|||
} |
|||
|
|||
private String getSignTxString(TxEntity txEntity) { |
|||
byte[] txData = Hex.decode(txEntity.getSignedHex()); |
|||
return Base43.encode(txData); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,143 @@ |
|||
/* |
|||
* Copyright (c) 2020 Cobo |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation, either version 3 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* in the file COPYING. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
package com.cobo.cold.ui.fragment.main.electrum; |
|||
|
|||
import android.content.Context; |
|||
import android.os.Bundle; |
|||
import android.text.TextUtils; |
|||
import android.view.View; |
|||
import android.widget.Toast; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.lifecycle.ViewModelProviders; |
|||
import androidx.recyclerview.widget.RecyclerView; |
|||
|
|||
import com.cobo.cold.R; |
|||
import com.cobo.cold.databinding.ElectrumTxnBinding; |
|||
import com.cobo.cold.databinding.TxnListBinding; |
|||
import com.cobo.cold.ui.MainActivity; |
|||
import com.cobo.cold.ui.common.BaseBindingAdapter; |
|||
import com.cobo.cold.ui.fragment.BaseFragment; |
|||
import com.cobo.cold.viewmodel.ElectrumViewModel; |
|||
|
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
import static com.cobo.cold.viewmodel.ElectrumViewModel.hasSdcard; |
|||
|
|||
public class ElectrumTxnListFragment extends BaseFragment<TxnListBinding> |
|||
implements Callback { |
|||
|
|||
public static final String TAG = "ElectrumTxnListFragment"; |
|||
private ElectrumViewModel viewModel; |
|||
private TxnAdapter adapter; |
|||
private AtomicBoolean showEmpty; |
|||
|
|||
@Override |
|||
protected int setView() { |
|||
return R.layout.txn_list; |
|||
} |
|||
|
|||
@Override |
|||
protected void init(View view) { |
|||
mActivity.setSupportActionBar(mBinding.toolbar); |
|||
mBinding.toolbar.setNavigationOnClickListener(((MainActivity) mActivity)::toggleDrawer); |
|||
mBinding.toolbar.setTitle(""); |
|||
viewModel = ViewModelProviders.of(mActivity).get(ElectrumViewModel.class); |
|||
adapter = new TxnAdapter(mActivity, this); |
|||
initViews(); |
|||
} |
|||
|
|||
private void initViews() { |
|||
showEmpty = new AtomicBoolean(false); |
|||
if (!hasSdcard(mActivity)) { |
|||
showEmpty.set(true); |
|||
mBinding.emptyTitle.setText(R.string.no_sdcard); |
|||
mBinding.emptyMessage.setText(R.string.no_sdcard_hint); |
|||
} else { |
|||
mBinding.list.setAdapter(adapter); |
|||
viewModel.loadUnsignTxn().observe(this, files -> { |
|||
if (files.size() > 0) { |
|||
adapter.setItems(files); |
|||
} else { |
|||
showEmpty.set(true); |
|||
mBinding.emptyTitle.setText(R.string.no_unsigned_txn); |
|||
mBinding.emptyMessage.setText(R.string.no_unsigned_txn_hint); |
|||
} |
|||
updateUi(); |
|||
}); |
|||
} |
|||
updateUi(); |
|||
} |
|||
|
|||
private void updateUi() { |
|||
if (showEmpty.get()) { |
|||
mBinding.emptyView.setVisibility(View.VISIBLE); |
|||
mBinding.list.setVisibility(View.GONE); |
|||
} else { |
|||
mBinding.emptyView.setVisibility(View.GONE); |
|||
mBinding.list.setVisibility(View.VISIBLE); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
protected void initData(Bundle savedInstanceState) { |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void onClick(String file) { |
|||
viewModel.parseTxnFile(file).observe(this, hex -> { |
|||
if (!TextUtils.isEmpty(hex)) { |
|||
Bundle bundle = new Bundle(); |
|||
bundle.putString("txn", hex); |
|||
bundle.putBoolean("is_file", true); |
|||
navigate(R.id.action_to_ElectrumTxConfirmFragment, bundle); |
|||
} else { |
|||
Toast.makeText(mActivity, R.string.error_txn_file, Toast.LENGTH_SHORT).show(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
|
|||
public static class TxnAdapter extends BaseBindingAdapter<String, ElectrumTxnBinding> { |
|||
private Callback callback; |
|||
|
|||
TxnAdapter(Context context, Callback callback) { |
|||
super(context); |
|||
this.callback = callback; |
|||
} |
|||
|
|||
@Override |
|||
protected int getLayoutResId(int viewType) { |
|||
return R.layout.electrum_txn; |
|||
} |
|||
|
|||
@Override |
|||
protected void onBindItem(ElectrumTxnBinding binding, String item) { |
|||
binding.setFile(item); |
|||
binding.setCallback(callback); |
|||
} |
|||
|
|||
@Override |
|||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { |
|||
super.onBindViewHolder(holder, position); |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,59 @@ |
|||
/* |
|||
* Copyright (c) 2020 Cobo |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation, either version 3 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* in the file COPYING. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
package com.cobo.cold.ui.modal; |
|||
|
|||
import android.app.AlertDialog; |
|||
import android.app.Dialog; |
|||
import android.os.Bundle; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.annotation.Nullable; |
|||
import androidx.databinding.DataBindingUtil; |
|||
import androidx.fragment.app.DialogFragment; |
|||
|
|||
import com.cobo.cold.R; |
|||
|
|||
|
|||
public class ExportToSdcardDialog extends DialogFragment { |
|||
|
|||
public static ExportToSdcardDialog newInstance() { |
|||
return new ExportToSdcardDialog(); |
|||
} |
|||
|
|||
@Nullable |
|||
@Override |
|||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, |
|||
@Nullable Bundle savedInstanceState) { |
|||
return super.onCreateView(inflater, container, savedInstanceState); |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { |
|||
View v = DataBindingUtil.inflate(LayoutInflater.from(getActivity()), |
|||
R.layout.export_success,null,false).getRoot(); |
|||
Dialog dialog = new AlertDialog.Builder(getActivity(), R.style.dialog) |
|||
.setView(v) |
|||
.create(); |
|||
dialog.setCanceledOnTouchOutside(false); |
|||
return dialog; |
|||
} |
|||
} |
@ -0,0 +1,227 @@ |
|||
/* |
|||
* Copyright (c) 2020 Cobo |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation, either version 3 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* in the file COPYING. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
package com.cobo.cold.viewmodel; |
|||
|
|||
import android.app.Application; |
|||
import android.content.Context; |
|||
import android.os.Handler; |
|||
import android.util.Log; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.appcompat.app.AppCompatActivity; |
|||
import androidx.databinding.DataBindingUtil; |
|||
import androidx.lifecycle.AndroidViewModel; |
|||
import androidx.lifecycle.LiveData; |
|||
import androidx.lifecycle.MutableLiveData; |
|||
|
|||
import com.cobo.coinlib.Util; |
|||
import com.cobo.coinlib.coins.BTC.Electrum.ElectrumTx; |
|||
import com.cobo.coinlib.coins.BTC.Electrum.TransactionInput; |
|||
import com.cobo.coinlib.coins.BTC.Electrum.TransactionOutput; |
|||
import com.cobo.coinlib.exception.InvalidPathException; |
|||
import com.cobo.coinlib.path.Account; |
|||
import com.cobo.coinlib.utils.Coins; |
|||
import com.cobo.cold.AppExecutors; |
|||
import com.cobo.cold.DataRepository; |
|||
import com.cobo.cold.MainApplication; |
|||
import com.cobo.cold.R; |
|||
import com.cobo.cold.databinding.CommonModalBinding; |
|||
import com.cobo.cold.db.entity.AccountEntity; |
|||
import com.cobo.cold.db.entity.CoinEntity; |
|||
import com.cobo.cold.protobuf.TransactionProtoc; |
|||
import com.cobo.cold.ui.modal.ExportToSdcardDialog; |
|||
import com.cobo.cold.ui.modal.ModalDialog; |
|||
import com.cobo.cold.update.utils.FileUtils; |
|||
import com.cobo.cold.update.utils.Storage; |
|||
import com.googlecode.protobuf.format.JsonFormat; |
|||
|
|||
import org.json.JSONArray; |
|||
import org.json.JSONException; |
|||
import org.json.JSONObject; |
|||
import org.spongycastle.util.encoders.Hex; |
|||
|
|||
import java.io.File; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.regex.Matcher; |
|||
import java.util.regex.Pattern; |
|||
|
|||
|
|||
public class ElectrumViewModel extends AndroidViewModel { |
|||
|
|||
public static final String ELECTRUM_SIGN_ID = "electrum_sign_id"; |
|||
|
|||
private static Pattern signedTxnPattern = Pattern.compile("[0-9a-f]{5}-signed.txn$"); |
|||
private final DataRepository mRepo; |
|||
private MutableLiveData<String> exPub = new MutableLiveData<>(); |
|||
private Storage storage; |
|||
|
|||
public ElectrumViewModel(@NonNull Application application) { |
|||
super(application); |
|||
mRepo = MainApplication.getApplication().getRepository(); |
|||
storage = Storage.createByEnvironment(application); |
|||
} |
|||
|
|||
public static boolean hasSdcard(Context context) { |
|||
Storage storage = Storage.createByEnvironment(context); |
|||
return storage != null && storage.getExternalDir() != null; |
|||
} |
|||
|
|||
public static boolean writeToSdcard(Storage storage, String content, String fileName) { |
|||
File file = new File(storage.getElectrumDir(), fileName); |
|||
return FileUtils.writeString(file, content); |
|||
} |
|||
|
|||
public static void showNoSdcardModal(AppCompatActivity activity) { |
|||
ModalDialog modalDialog = ModalDialog.newInstance(); |
|||
CommonModalBinding binding = DataBindingUtil.inflate( |
|||
LayoutInflater.from(activity), R.layout.common_modal, |
|||
null, false); |
|||
binding.title.setText(R.string.hint); |
|||
binding.subTitle.setText(R.string.insert_sdcard_hint); |
|||
binding.close.setVisibility(View.GONE); |
|||
binding.confirm.setText(R.string.know); |
|||
binding.confirm.setOnClickListener(vv -> modalDialog.dismiss()); |
|||
modalDialog.setBinding(binding); |
|||
modalDialog.show(activity.getSupportFragmentManager(), ""); |
|||
} |
|||
|
|||
public static void exportSuccess(AppCompatActivity activity) { |
|||
ExportToSdcardDialog dialog = new ExportToSdcardDialog(); |
|||
dialog.show(activity.getSupportFragmentManager(), ""); |
|||
new Handler().postDelayed(dialog::dismiss, 1000); |
|||
} |
|||
|
|||
static JSONObject parseElectrumTxHex(String hex) throws JSONException, ElectrumTx.SerializationException { |
|||
ElectrumTx tx = ElectrumTx.parse(Hex.decode(hex)); |
|||
JSONObject btcTx = adapt(tx); |
|||
TransactionProtoc.SignTransaction.Builder builder = TransactionProtoc.SignTransaction.newBuilder(); |
|||
builder.setCoinCode(Coins.BTC.coinCode()) |
|||
.setSignId(ELECTRUM_SIGN_ID) |
|||
.setTimestamp(System.currentTimeMillis()) |
|||
.setDecimal(8); |
|||
String signTransaction = new JsonFormat().printToString(builder.build()); |
|||
JSONObject signTx = new JSONObject(signTransaction); |
|||
signTx.put("btcTx", btcTx); |
|||
return signTx; |
|||
} |
|||
|
|||
private static JSONObject adapt(ElectrumTx tx) throws JSONException { |
|||
JSONObject object = new JSONObject(); |
|||
JSONArray inputs = new JSONArray(); |
|||
JSONArray outputs = new JSONArray(); |
|||
adaptInputs(tx, inputs); |
|||
adaptOutputs(tx, outputs); |
|||
object.put("inputs", inputs); |
|||
object.put("outputs", outputs); |
|||
object.put("locktime", tx.getLockTime()); |
|||
object.put("version", tx.getVersion()); |
|||
return object; |
|||
} |
|||
|
|||
private static void adaptInputs(ElectrumTx tx, JSONArray inputs) throws JSONException { |
|||
for (TransactionInput transactionInput : tx.getInputs()) { |
|||
JSONObject in = new JSONObject(); |
|||
JSONObject utxo = new JSONObject(); |
|||
in.put("hash", transactionInput.preTxId); |
|||
in.put("index", transactionInput.preTxIndex); |
|||
in.put("sequence", transactionInput.sequence); |
|||
utxo.put("publicKey", transactionInput.pubKey.pubkey); |
|||
utxo.put("value", transactionInput.value.intValue()); |
|||
in.put("utxo", utxo); |
|||
in.put("hash", transactionInput.preTxId); |
|||
in.put("ownerKeyPath", transactionInput.pubKey.hdPath); |
|||
inputs.put(in); |
|||
|
|||
} |
|||
} |
|||
|
|||
private static void adaptOutputs(ElectrumTx tx, JSONArray outputs) throws JSONException { |
|||
for (TransactionOutput transactionOutput : tx.getOutputs()) { |
|||
JSONObject out = new JSONObject(); |
|||
out.put("address", transactionOutput.address); |
|||
out.put("value", transactionOutput.value); |
|||
outputs.put(out); |
|||
} |
|||
} |
|||
|
|||
public LiveData<String> getExPub() { |
|||
AppExecutors.getInstance().diskIO().execute(() -> { |
|||
CoinEntity btc = mRepo.loadCoinSync(Coins.coinIdFromCoinCode("BTC")); |
|||
AccountEntity accountEntity = mRepo.loadAccountsForCoin(btc).get(0); |
|||
String hdPath = accountEntity.getHdPath(); |
|||
String expub = accountEntity.getExPub(); |
|||
try { |
|||
Account account = Account.parseAccount(hdPath); |
|||
if (account.getParent().getParent().getValue() == 49 && expub.startsWith("xpub")) { |
|||
exPub.postValue(Util.convertXpubToYpub(expub)); |
|||
} else if (expub.startsWith("ypub")) { |
|||
exPub.postValue(expub); |
|||
} |
|||
} catch (InvalidPathException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
|
|||
}); |
|||
return exPub; |
|||
} |
|||
|
|||
private boolean isSignedTxn(String fileName) { |
|||
Matcher matcher = signedTxnPattern.matcher(fileName); |
|||
return matcher.matches(); |
|||
} |
|||
|
|||
public LiveData<List<String>> loadUnsignTxn() { |
|||
MutableLiveData<List<String>> result = new MutableLiveData<>(); |
|||
AppExecutors.getInstance().diskIO().execute(() -> { |
|||
List<String> fileList = new ArrayList<>(); |
|||
if (storage != null) { |
|||
File[] files = storage.getElectrumDir().listFiles(); |
|||
if (files != null) { |
|||
for (File f : files) { |
|||
Log.w("kkk", f.getName() + " " + f.length()); |
|||
if (f.getName().endsWith(".txn") |
|||
&& !isSignedTxn(f.getName())) { |
|||
fileList.add(f.getName()); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
result.postValue(fileList); |
|||
}); |
|||
return result; |
|||
} |
|||
|
|||
public LiveData<String> parseTxnFile(String file) { |
|||
MutableLiveData<String> txnHex = new MutableLiveData<>(); |
|||
AppExecutors.getInstance().diskIO().execute(() -> { |
|||
String content = FileUtils.readString(new File(storage.getExternalDir(), file)); |
|||
try { |
|||
JSONObject object = new JSONObject(content); |
|||
String hex = object.getString("hex"); |
|||
txnHex.postValue(hex); |
|||
} catch (JSONException e) { |
|||
e.printStackTrace(); |
|||
txnHex.postValue(null); |
|||
} |
|||
}); |
|||
return txnHex; |
|||
} |
|||
} |
After Width: | Height: | Size: 699 B |
After Width: | Height: | Size: 1014 B |
After Width: | Height: | Size: 330 B |
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,136 @@ |
|||
<?xml version="1.0" encoding="utf-8"?><!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout 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"> |
|||
|
|||
<data> |
|||
|
|||
<variable |
|||
name="coinCode" |
|||
type="String" /> |
|||
</data> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:orientation="vertical"> |
|||
|
|||
<androidx.appcompat.widget.Toolbar |
|||
android:id="@+id/toolbar" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="?attr/actionBarSize" |
|||
android:background="?attr/colorPrimary" |
|||
app:navigationIcon="@drawable/arrow_left" |
|||
app:popupTheme="@style/AppTheme.PopupOverlay"> |
|||
|
|||
<TextView |
|||
android:id="@+id/toolbar_title" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:text="@string/broadcast_tx" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="15sp" |
|||
tools:text="@string/broadcast_tx" /> |
|||
</androidx.appcompat.widget.Toolbar> |
|||
|
|||
<include layout="@layout/divider" /> |
|||
|
|||
<ScrollView |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent"> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:gravity="center_horizontal" |
|||
android:orientation="vertical"> |
|||
|
|||
<ImageView |
|||
android:id="@+id/icon" |
|||
android:layout_width="48dp" |
|||
android:layout_height="48dp" |
|||
android:layout_marginTop="20dp" |
|||
android:src="@drawable/coin_btc" |
|||
tools:ignore="ContentDescription" /> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="16dp" |
|||
android:gravity="center_vertical" |
|||
android:orientation="horizontal" |
|||
android:paddingHorizontal="16dp"> |
|||
|
|||
<View |
|||
android:layout_width="30dp" |
|||
android:layout_height="match_parent" /> |
|||
|
|||
<TextView |
|||
android:layout_width="0dp" |
|||
android:layout_height="wrap_content" |
|||
android:layout_weight="1" |
|||
android:gravity="center" |
|||
android:text="@string/use_electrum_to_broadcast" |
|||
android:textColor="@color/white" |
|||
android:textSize="15sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<ImageView |
|||
android:id="@+id/info" |
|||
android:layout_width="30dp" |
|||
android:layout_height="30dp" |
|||
android:padding="5dp" |
|||
android:src="@drawable/info" /> |
|||
|
|||
</LinearLayout> |
|||
|
|||
<TextView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="12dp" |
|||
android:text="@string/transaction_from_electrum" |
|||
android:textColor="@color/white40" /> |
|||
|
|||
<include |
|||
android:id="@+id/qrcode_layout" |
|||
layout="@layout/qrcode" /> |
|||
|
|||
<com.cobo.cold.ui.views.SpanedTextView |
|||
android:id="@+id/hint" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:layout_marginTop="26dp" |
|||
android:gravity="center" |
|||
android:text="@string/electrum_qrcode_hint" |
|||
android:textColor="@color/white" |
|||
android:textSize="12sp" /> |
|||
|
|||
<Button |
|||
android:id="@+id/complete" |
|||
style="@style/AcceptButton" |
|||
android:layout_width="match_parent" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:layout_marginVertical="20dp" |
|||
android:text="@string/complete" /> |
|||
</LinearLayout> |
|||
</ScrollView> |
|||
</LinearLayout> |
|||
</layout> |
@ -0,0 +1,86 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
|
|||
<data> |
|||
|
|||
</data> |
|||
|
|||
<LinearLayout |
|||
android:orientation="vertical" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:background="#181717"> |
|||
|
|||
<RelativeLayout |
|||
android:id="@+id/add_address" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="53dp" |
|||
android:orientation="horizontal" |
|||
android:background="?attr/selectableItemBackground"> |
|||
|
|||
<TextView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:text="@string/add_address" |
|||
android:layout_centerVertical="true" |
|||
android:paddingHorizontal="16dp" |
|||
android:textColor="@color/white" /> |
|||
|
|||
<ImageView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:src="@drawable/arrow_right" |
|||
android:layout_centerVertical="true" |
|||
android:layout_alignParentEnd="true" |
|||
android:layout_marginEnd="16dp" /> |
|||
</RelativeLayout> |
|||
|
|||
<View |
|||
android:layout_width="match_parent" |
|||
android:layout_height="1dp" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:background="#12ffffff" /> |
|||
|
|||
<RelativeLayout |
|||
android:id="@+id/export_xpub_to_electrum" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="53dp" |
|||
android:orientation="horizontal" |
|||
android:background="?attr/selectableItemBackground"> |
|||
|
|||
<TextView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:text="@string/export_to_electrum" |
|||
android:layout_centerVertical="true" |
|||
android:paddingHorizontal="16dp" |
|||
android:textColor="@color/white" /> |
|||
|
|||
<ImageView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:src="@drawable/arrow_right" |
|||
android:layout_centerVertical="true" |
|||
android:layout_alignParentEnd="true" |
|||
android:layout_marginEnd="16dp" /> |
|||
</RelativeLayout> |
|||
|
|||
</LinearLayout> |
|||
</layout> |
@ -0,0 +1,54 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout xmlns:tools="http://schemas.android.com/tools" |
|||
xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
|
|||
<data> |
|||
|
|||
</data> |
|||
|
|||
<FrameLayout |
|||
android:orientation="vertical" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="530dp" |
|||
android:background="#ffffff"> |
|||
|
|||
<ImageView |
|||
android:id="@+id/close" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:src="@drawable/close" |
|||
android:tint="@color/colorAccent" |
|||
android:padding="18dp" |
|||
android:layout_gravity="end|top" |
|||
tools:ignore="ContentDescription" /> |
|||
|
|||
<FrameLayout |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center"> |
|||
|
|||
<include |
|||
android:id="@+id/qrcode_layout" |
|||
layout="@layout/dynamic_qrcode" /> |
|||
</FrameLayout> |
|||
|
|||
|
|||
</FrameLayout> |
|||
</layout> |
@ -0,0 +1,139 @@ |
|||
<?xml version="1.0" encoding="utf-8"?><!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout 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"> |
|||
|
|||
<data> |
|||
|
|||
</data> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:gravity="center_horizontal" |
|||
android:orientation="vertical"> |
|||
|
|||
<androidx.appcompat.widget.Toolbar |
|||
android:id="@+id/toolbar" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="?attr/actionBarSize" |
|||
android:background="?attr/colorPrimary" |
|||
app:navigationIcon="@drawable/arrow_left" |
|||
app:popupTheme="@style/AppTheme.PopupOverlay"> |
|||
|
|||
<TextView |
|||
android:id="@+id/toolbar_title" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:layout_marginEnd="20dp" |
|||
android:ellipsize="middle" |
|||
android:singleLine="true" |
|||
android:text="@string/export_to_electrum" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="15sp" /> |
|||
</androidx.appcompat.widget.Toolbar> |
|||
|
|||
<include layout="@layout/divider" /> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="40dp" |
|||
android:gravity="center"> |
|||
<TextView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:gravity="center" |
|||
android:text="@string/use_electrum_scan_xpub" |
|||
android:textColor="@color/white" |
|||
android:textSize="15sp" |
|||
android:textStyle="bold" /> |
|||
<ImageView |
|||
android:id="@+id/info" |
|||
android:layout_width="30dp" |
|||
android:layout_height="30dp" |
|||
android:padding="5dp" |
|||
android:src="@drawable/info"/> |
|||
</LinearLayout> |
|||
|
|||
<com.cobo.cold.ui.views.qrcode.QrCodeView |
|||
android:id="@+id/qrcode" |
|||
android:layout_width="160dp" |
|||
android:layout_height="160dp" |
|||
android:layout_marginHorizontal="34dp" |
|||
android:layout_marginTop="24dp" |
|||
android:background="@color/white" |
|||
android:padding="5dp" |
|||
android:keepScreenOn="true"> |
|||
|
|||
<ImageView |
|||
android:id="@+id/img" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:visibility="visible" |
|||
tools:ignore="ContentDescription" /> |
|||
|
|||
<ProgressBar |
|||
android:id="@+id/progress" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:visibility="visible" /> |
|||
</com.cobo.cold.ui.views.qrcode.QrCodeView> |
|||
|
|||
<com.cobo.cold.ui.views.SpanedTextView |
|||
android:id="@+id/export_to_sdcard" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:layout_marginTop="26dp" |
|||
android:gravity="center" |
|||
android:text="@string/electrum_qrcode_hint" |
|||
android:textColor="@color/white" |
|||
android:textSize="12sp" /> |
|||
|
|||
|
|||
<androidx.legacy.widget.Space |
|||
android:layout_width="match_parent" |
|||
android:layout_height="0dp" |
|||
android:layout_weight="1"/> |
|||
<TextView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="40dp" |
|||
android:gravity="center" |
|||
android:text="@string/master_xpub" |
|||
android:textColor="@color/white" |
|||
android:textSize="15sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/expub" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="8dp" |
|||
android:gravity="center" |
|||
tools:text="ypub6D3i46Y43SFfjEBYheBK3btYMRm9Cfb8Tt4M5Bv16tArNBw5ATNyJWjdcMyLxoCdHWTvm3ak7j2BWacq5Lw478aYUeARoYm4dvaQgJBAGsb" |
|||
android:textColor="@color/white40" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:layout_marginBottom="48dp" |
|||
android:textSize="15sp" /> |
|||
</LinearLayout> |
|||
</layout> |
@ -0,0 +1,86 @@ |
|||
<?xml version="1.0" encoding="utf-8"?><!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:app="http://schemas.android.com/apk/res-auto"> |
|||
|
|||
<data> |
|||
|
|||
</data> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:orientation="vertical"> |
|||
|
|||
<androidx.appcompat.widget.Toolbar |
|||
android:id="@+id/toolbar" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="?attr/actionBarSize" |
|||
android:background="?attr/colorPrimary" |
|||
app:navigationIcon="@drawable/arrow_left" |
|||
app:popupTheme="@style/AppTheme.PopupOverlay"> |
|||
|
|||
<TextView |
|||
android:id="@+id/toolbar_title" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:layout_marginEnd="20dp" |
|||
android:ellipsize="middle" |
|||
android:singleLine="true" |
|||
android:text="@string/export_to_electrum" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="15sp" /> |
|||
</androidx.appcompat.widget.Toolbar> |
|||
|
|||
<include layout="@layout/divider" /> |
|||
|
|||
<TextView |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="16dp" |
|||
android:padding="16dp" |
|||
android:text="@string/export_to_electrum_guide_hint" |
|||
android:textColor="@color/white" |
|||
android:textSize="15sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<TextView |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:lineSpacingExtra="6dp" |
|||
android:padding="16dp" |
|||
android:text="@string/export_to_electrum_guide" |
|||
android:textColor="@color/white" |
|||
android:textSize="13sp" /> |
|||
|
|||
<Space |
|||
android:layout_width="match_parent" |
|||
android:layout_height="0dp" |
|||
android:layout_weight="1" /> |
|||
|
|||
<Button |
|||
android:id="@+id/export" |
|||
style="@style/AcceptButton" |
|||
android:layout_width="match_parent" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:layout_marginBottom="20dp" |
|||
android:text="@string/export_xpub" /> |
|||
|
|||
</LinearLayout> |
|||
</layout> |
@ -0,0 +1,69 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:app="http://schemas.android.com/apk/res-auto" |
|||
xmlns:bind="http://schemas.android.com/apk/res-auto"> |
|||
|
|||
<data> |
|||
|
|||
<variable |
|||
name="tx" |
|||
type="com.cobo.cold.model.Tx" /> |
|||
</data> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:orientation="vertical"> |
|||
|
|||
<androidx.appcompat.widget.Toolbar |
|||
android:id="@+id/toolbar" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="?attr/actionBarSize" |
|||
android:background="?attr/colorPrimary" |
|||
app:navigationIcon="@drawable/arrow_left" |
|||
app:popupTheme="@style/AppTheme.PopupOverlay"> |
|||
|
|||
<TextView |
|||
android:id="@+id/toolbar_title" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:textSize="15sp" |
|||
android:textColor="@android:color/white" |
|||
android:text="@string/signing_history" /> |
|||
</androidx.appcompat.widget.Toolbar> |
|||
|
|||
<include layout="@layout/divider" /> |
|||
|
|||
<LinearLayout |
|||
android:orientation="vertical" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent"> |
|||
|
|||
<include |
|||
android:id="@+id/tx_detail" |
|||
layout="@layout/electrum_tx_detail" |
|||
bind:tx="@{tx}" /> |
|||
|
|||
</LinearLayout> |
|||
|
|||
</LinearLayout> |
|||
|
|||
</layout> |
@ -0,0 +1,89 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:app="http://schemas.android.com/apk/res-auto" |
|||
xmlns:bind="http://schemas.android.com/apk/res-auto"> |
|||
|
|||
<data> |
|||
|
|||
<variable |
|||
name="coinName" |
|||
type="String" /> |
|||
|
|||
<variable |
|||
name="tx" |
|||
type="com.cobo.cold.model.Tx" /> |
|||
|
|||
<variable |
|||
name="viewModel" |
|||
type="com.cobo.cold.viewmodel.TxConfirmViewModel" /> |
|||
</data> |
|||
|
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:orientation="vertical"> |
|||
|
|||
<androidx.appcompat.widget.Toolbar |
|||
android:id="@+id/toolbar" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="?attr/actionBarSize" |
|||
android:background="?attr/colorPrimary" |
|||
app:navigationIcon="@drawable/arrow_left" |
|||
app:popupTheme="@style/AppTheme.PopupOverlay"> |
|||
|
|||
<TextView |
|||
android:id="@+id/toolbar_title" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:text="@string/tx_confirm" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="15sp" /> |
|||
</androidx.appcompat.widget.Toolbar> |
|||
|
|||
<include layout="@layout/divider" /> |
|||
|
|||
<LinearLayout |
|||
android:id="@+id/transaction_info" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="0dp" |
|||
android:layout_weight="1" |
|||
android:orientation="vertical"> |
|||
|
|||
<include |
|||
android:id="@+id/tx_detail" |
|||
layout="@layout/electrum_tx_detail" |
|||
bind:tx="@{tx}" /> |
|||
</LinearLayout> |
|||
|
|||
<Button |
|||
android:id="@+id/sign" |
|||
style="@style/AcceptButton" |
|||
android:layout_width="match_parent" |
|||
android:layout_marginTop="16dp" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:layout_marginBottom="20dp" |
|||
android:text="@string/sign" /> |
|||
|
|||
|
|||
</LinearLayout> |
|||
|
|||
</layout> |
@ -0,0 +1,312 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout xmlns:app="http://schemas.android.com/apk/res-auto" |
|||
xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:tools="http://schemas.android.com/tools"> |
|||
|
|||
<data> |
|||
|
|||
<variable |
|||
name="tx" |
|||
type="com.cobo.cold.model.Tx" /> |
|||
</data> |
|||
|
|||
<com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:orientation="vertical" |
|||
tools:showIn="@layout/tx_confirm_fragment"> |
|||
|
|||
<RelativeLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="60dp"> |
|||
|
|||
<ImageView |
|||
android:id="@+id/icon" |
|||
android:layout_width="28dp" |
|||
android:layout_height="28dp" |
|||
android:layout_centerVertical="true" |
|||
android:layout_marginStart="16dp" |
|||
android:src="@drawable/coin_btc" |
|||
tools:ignore="ContentDescription" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/coinId" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_below="@id/coinCode" |
|||
android:layout_centerInParent="true" |
|||
android:layout_marginStart="12dp" |
|||
android:layout_marginTop="2dp" |
|||
android:layout_toEndOf="@id/icon" |
|||
android:textColor="@color/white40" |
|||
android:textSize="12sp" |
|||
android:textStyle="bold" |
|||
android:text="Bitcoin" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/unit" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_alignParentEnd="true" |
|||
android:layout_marginStart="4dp" |
|||
android:layout_marginTop="14dp" |
|||
android:layout_marginEnd="16dp" |
|||
android:text="@{tx.coinCode}" |
|||
android:textColor="@color/white" |
|||
android:textSize="14sp" |
|||
android:textStyle="bold" |
|||
tools:text="BTC" |
|||
android:visibility="gone" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/amount" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginStart="12dp" |
|||
android:layout_marginTop="14dp" |
|||
android:layout_toStartOf="@id/unit" |
|||
android:layout_alignParentEnd="true" |
|||
android:layout_marginEnd="16dp" |
|||
android:textColor="@color/white" |
|||
android:textSize="14sp" |
|||
android:textStyle="bold" |
|||
tools:text="2.62407806" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/time" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_below="@id/amount" |
|||
android:layout_alignParentEnd="true" |
|||
android:layout_marginStart="12dp" |
|||
android:layout_marginTop="2dp" |
|||
android:layout_marginEnd="16dp" |
|||
android:textColor="@color/white40" |
|||
android:textSize="12sp" |
|||
android:textStyle="bold" |
|||
app:time="@{tx.timeStamp}" |
|||
tools:text="2018/06/01 15:40" /> |
|||
|
|||
<include |
|||
layout="@layout/divider" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="1dp" |
|||
android:layout_alignParentBottom="true" /> |
|||
</RelativeLayout> |
|||
|
|||
<RelativeLayout |
|||
android:id="@+id/tx_id_info" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="86dp"> |
|||
|
|||
<TextView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginStart="16dp" |
|||
android:layout_marginTop="14dp" |
|||
android:text="@string/tx_id" |
|||
android:textColor="@color/white40" |
|||
android:textSize="14sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<TextView |
|||
android:layout_width="184dp" |
|||
android:layout_height="wrap_content" |
|||
android:layout_alignParentEnd="true" |
|||
android:layout_marginTop="14dp" |
|||
android:layout_marginEnd="16dp" |
|||
android:text="@{tx.txId}" |
|||
android:textColor="@color/white" |
|||
android:textStyle="bold" |
|||
tools:text="84asf56sa5ewf46a4s654f6sa46s4z6x46sa46s46d4sa6f4a64f6ad4f6as4dx556s4a" /> |
|||
|
|||
<include |
|||
layout="@layout/divider" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="1dp" |
|||
android:layout_alignParentBottom="true" /> |
|||
</RelativeLayout> |
|||
|
|||
<RelativeLayout |
|||
android:id="@+id/tx_source" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="60dp" |
|||
android:gravity="center_vertical"> |
|||
|
|||
<TextView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginStart="16dp" |
|||
android:text="@string/transaction_source_label" |
|||
android:layout_centerVertical="true" |
|||
android:textColor="@color/white40" |
|||
android:textSize="14sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<TextView |
|||
android:layout_width="184dp" |
|||
android:layout_height="wrap_content" |
|||
android:layout_alignParentEnd="true" |
|||
android:layout_centerVertical="true" |
|||
android:layout_marginEnd="16dp" |
|||
android:textColor="@color/white" |
|||
android:textStyle="bold" |
|||
android:text="Electrum" /> |
|||
|
|||
<include |
|||
layout="@layout/divider" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="1dp" |
|||
android:layout_alignParentBottom="true" /> |
|||
</RelativeLayout> |
|||
|
|||
<androidx.recyclerview.widget.RecyclerView |
|||
android:id="@+id/from_list" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" |
|||
tools:listitem="@layout/receive_item" |
|||
tools:itemCount="1" |
|||
android:visibility="visible" /> |
|||
<RelativeLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content"> |
|||
<ImageView |
|||
android:id="@+id/arrow_down" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginVertical="8dp" |
|||
android:layout_marginStart="120dp" |
|||
android:src="@drawable/tx_arrow_down" |
|||
tools:ignore="ContentDescription" /> |
|||
</RelativeLayout> |
|||
<androidx.recyclerview.widget.RecyclerView |
|||
android:id="@+id/to_list" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
tools:itemCount="1" |
|||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" |
|||
tools:listitem="@layout/receive_item" |
|||
android:visibility="visible" /> |
|||
|
|||
<include |
|||
layout="@layout/divider" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="1dp" /> |
|||
|
|||
<RelativeLayout |
|||
android:id="@+id/fee_info" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="49dp"> |
|||
|
|||
<TextView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginStart="16dp" |
|||
android:layout_marginTop="14dp" |
|||
android:text="@string/tx_fee" |
|||
android:textColor="@color/white40" |
|||
android:textSize="14sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/fee" |
|||
android:layout_width="184dp" |
|||
android:layout_height="wrap_content" |
|||
android:layout_alignParentEnd="true" |
|||
android:layout_marginTop="14dp" |
|||
android:layout_marginEnd="16dp" |
|||
android:text="@{tx.fee}" |
|||
android:textColor="@color/white" |
|||
android:textStyle="bold" |
|||
tools:text="0.00006840 BTC" /> |
|||
|
|||
<include |
|||
layout="@layout/divider" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="1dp" |
|||
android:layout_alignParentBottom="true" /> |
|||
</RelativeLayout> |
|||
|
|||
<RelativeLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="60dp" |
|||
android:paddingTop="14dp"> |
|||
|
|||
<TextView |
|||
android:id="@+id/memo_label" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginStart="16dp" |
|||
android:text="@string/tx_memo" |
|||
android:textColor="@color/white40" |
|||
android:textSize="14sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/memo_edit" |
|||
android:layout_width="184dp" |
|||
android:layout_height="wrap_content" |
|||
android:layout_alignParentEnd="true" |
|||
android:layout_marginBottom="14dp" |
|||
android:layout_marginEnd="16dp" |
|||
android:maxLines="2" |
|||
android:ellipsize="end" |
|||
android:text="@{tx.memo}" |
|||
android:textColor="@color/white" |
|||
android:textStyle="bold" |
|||
tools:text="memo" /> |
|||
|
|||
<include |
|||
layout="@layout/divider" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="1dp" |
|||
android:layout_alignParentBottom="true" /> |
|||
</RelativeLayout> |
|||
<include |
|||
android:id="@+id/qrcode_layout" |
|||
layout="@layout/qrcode" |
|||
android:layout_height="wrap_content" |
|||
android:layout_width="match_parent"/> |
|||
|
|||
<LinearLayout |
|||
android:id="@+id/export" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:orientation="vertical"> |
|||
<Button |
|||
android:id="@+id/export_to_sdcard" |
|||
android:layout_width="match_parent" |
|||
style="@style/AcceptButton" |
|||
android:layout_marginTop="16dp" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:text="@string/export_signed_txn_file"/> |
|||
<TextView |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginVertical="16dp" |
|||
android:paddingHorizontal="16dp" |
|||
android:textColor="@color/white" |
|||
android:text="@string/export_signed_txn_action_guide" |
|||
android:gravity="center"/> |
|||
</LinearLayout> |
|||
|
|||
</com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout> |
|||
</layout> |
@ -0,0 +1,46 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:tools="http://schemas.android.com/tools"> |
|||
|
|||
<data> |
|||
|
|||
<variable |
|||
name="callback" |
|||
type="com.cobo.cold.ui.fragment.main.electrum.Callback" /> |
|||
<variable |
|||
name="file" |
|||
type="String" /> |
|||
</data> |
|||
|
|||
<RelativeLayout |
|||
android:orientation="vertical" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="45dp" |
|||
android:paddingHorizontal="16dp" |
|||
android:background="?attr/selectableItemBackground" |
|||
android:onClick="@{()->callback.onClick(file)}"> |
|||
<TextView |
|||
android:id="@+id/file_name" |
|||
android:layout_width="260dp" |
|||
android:layout_height="wrap_content" |
|||
tools:text="unsigned-1.txn" |
|||
android:layout_centerVertical="true" |
|||
android:textSize="15sp" |
|||
android:text="@{file}" |
|||
android:singleLine="true" |
|||
android:ellipsize="middle" |
|||
android:textColor="@color/white"/> |
|||
<ImageView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:src="@drawable/arrow_right" |
|||
android:layout_centerVertical="true" |
|||
android:layout_alignParentEnd="true"/> |
|||
<include |
|||
layout="@layout/divider" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="1dp" |
|||
android:layout_alignParentBottom="true" /> |
|||
|
|||
</RelativeLayout> |
|||
</layout> |
@ -0,0 +1,117 @@ |
|||
<?xml version="1.0" encoding="utf-8"?><!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:tools="http://schemas.android.com/tools"> |
|||
|
|||
<data /> |
|||
|
|||
<FrameLayout |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center"> |
|||
|
|||
<RelativeLayout |
|||
android:layout_width="288dp" |
|||
android:layout_height="wrap_content" |
|||
android:background="@drawable/modal_bg"> |
|||
|
|||
|
|||
<TextView |
|||
android:id="@+id/title" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_centerHorizontal="true" |
|||
android:layout_marginTop="12dp" |
|||
android:textColor="@color/black" |
|||
android:textSize="15sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/file_name_label" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_below="@id/title" |
|||
android:layout_centerHorizontal="true" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:layout_marginTop="12dp" |
|||
android:gravity="center_horizontal" |
|||
android:textSize="13sp" |
|||
android:visibility="visible" |
|||
android:text="@string/file_name_label" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/file_name" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_below="@id/file_name_label" |
|||
android:layout_centerHorizontal="true" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:gravity="center_horizontal" |
|||
android:textColor="@color/black" |
|||
android:textSize="13sp" |
|||
android:textStyle="bold" |
|||
android:visibility="visible" |
|||
tools:text="CV-P2PKH-pubkey.txt" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/action_hint" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_below="@id/file_name" |
|||
android:layout_centerHorizontal="true" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:gravity="center_horizontal" |
|||
android:textSize="13sp" |
|||
android:visibility="visible" /> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_below="@id/action_hint" |
|||
android:orientation="horizontal"> |
|||
|
|||
<Button |
|||
android:id="@+id/cancel" |
|||
style="@style/AcceptButton" |
|||
android:layout_width="0dp" |
|||
android:layout_marginStart="16dp" |
|||
android:layout_marginTop="16dp" |
|||
android:layout_marginBottom="20dp" |
|||
android:layout_weight="1" |
|||
android:background="#EBF0F5" |
|||
android:text="@string/cancel" |
|||
android:textColor="#8F95AA" |
|||
android:textStyle="bold" /> |
|||
|
|||
<Button |
|||
android:id="@+id/confirm" |
|||
style="@style/AcceptButton" |
|||
android:layout_width="0dp" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:layout_marginTop="16dp" |
|||
android:layout_marginBottom="20dp" |
|||
android:layout_weight="1" |
|||
android:text="@string/export" |
|||
android:textStyle="bold" /> |
|||
</LinearLayout> |
|||
|
|||
|
|||
</RelativeLayout> |
|||
|
|||
</FrameLayout> |
|||
</layout> |
@ -0,0 +1,60 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:tools="http://schemas.android.com/tools"> |
|||
|
|||
<data> |
|||
|
|||
</data> |
|||
|
|||
<FrameLayout |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:background="@drawable/modal_bg" |
|||
android:paddingVertical="20dp"> |
|||
|
|||
<LinearLayout |
|||
android:id="@+id/success" |
|||
android:layout_width="224dp" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:gravity="center" |
|||
android:orientation="vertical"> |
|||
|
|||
<ImageView |
|||
android:layout_width="48dp" |
|||
android:layout_height="48dp" |
|||
android:src="@drawable/circle_positive" |
|||
android:tint="@color/colorAccent" |
|||
tools:ignore="ContentDescription" /> |
|||
|
|||
<TextView |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="16dp" |
|||
android:textSize="15sp" |
|||
android:textStyle="bold" |
|||
android:textColor="@color/black" |
|||
android:text="@string/export_success" /> |
|||
|
|||
</LinearLayout> |
|||
|
|||
</FrameLayout> |
|||
</layout> |
@ -0,0 +1,58 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout xmlns:tools="http://schemas.android.com/tools" |
|||
xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
|
|||
<data> |
|||
|
|||
</data> |
|||
|
|||
<com.cobo.cold.ui.views.qrcode.QrCodeView |
|||
android:id="@+id/qrcode" |
|||
android:layout_width="260dp" |
|||
android:layout_height="260dp" |
|||
android:layout_marginTop="12dp" |
|||
android:layout_gravity="center" |
|||
android:orientation="vertical"> |
|||
|
|||
<FrameLayout |
|||
android:layout_width="260dp" |
|||
android:layout_height="260dp" |
|||
android:layout_gravity="center_horizontal" |
|||
android:background="@color/white" |
|||
android:keepScreenOn="true"> |
|||
|
|||
<ImageView |
|||
android:id="@+id/img" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:layout_gravity="center" |
|||
android:visibility="visible" |
|||
android:padding="20dp" |
|||
tools:ignore="ContentDescription"/> |
|||
|
|||
<ProgressBar |
|||
android:id="@+id/progress" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:visibility="visible" /> |
|||
</FrameLayout> |
|||
</com.cobo.cold.ui.views.qrcode.QrCodeView> |
|||
</layout> |
@ -0,0 +1,95 @@ |
|||
<?xml version="1.0" encoding="utf-8"?><!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<layout 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"> |
|||
|
|||
<data> |
|||
</data> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:orientation="vertical"> |
|||
|
|||
<androidx.appcompat.widget.Toolbar |
|||
android:id="@+id/toolbar" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="?attr/actionBarSize" |
|||
android:background="?attr/colorPrimary" |
|||
app:navigationIcon="@drawable/menu" |
|||
app:popupTheme="@style/AppTheme.PopupOverlay"> |
|||
|
|||
<TextView |
|||
android:id="@+id/toolbar_title" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:text="对TF卡内文件签名" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="15sp" /> |
|||
</androidx.appcompat.widget.Toolbar> |
|||
|
|||
<include layout="@layout/divider" /> |
|||
|
|||
<androidx.recyclerview.widget.RecyclerView |
|||
android:id="@+id/list" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
tools:listitem="@layout/electrum_txn" |
|||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/> |
|||
|
|||
<LinearLayout |
|||
android:id="@+id/empty_view" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="60dp" |
|||
android:gravity="center_horizontal" |
|||
android:orientation="vertical" |
|||
android:visibility="gone"> |
|||
|
|||
<ImageView |
|||
android:layout_width="36dp" |
|||
android:layout_height="36dp" |
|||
android:src="@drawable/sdcard_icon" |
|||
tools:ignore="ContentDescription" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/empty_title" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="16dp" |
|||
android:textColor="@color/white" |
|||
android:textSize="15sp" |
|||
android:textStyle="bold"/> |
|||
|
|||
<TextView |
|||
android:id="@+id/empty_message" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:textColor="@color/white40" |
|||
android:layout_marginHorizontal="16dp" |
|||
android:layout_marginTop="8dp" |
|||
android:gravity="center"/> |
|||
|
|||
|
|||
</LinearLayout> |
|||
|
|||
|
|||
</LinearLayout> |
|||
</layout> |
@ -0,0 +1,37 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
~ Copyright (c) 2020 Cobo |
|||
~ |
|||
~ This program is free software: you can redistribute it and/or modify |
|||
~ it under the terms of the GNU General Public License as published by |
|||
~ the Free Software Foundation, either version 3 of the License, or |
|||
~ (at your option) any later version. |
|||
~ |
|||
~ This program is distributed in the hope that it will be useful, |
|||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
~ GNU General Public License for more details. |
|||
~ |
|||
~ You should have received a copy of the GNU General Public License |
|||
~ in the file COPYING. If not, see <http://www.gnu.org/licenses/>. |
|||
--> |
|||
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:app="http://schemas.android.com/apk/res-auto"> |
|||
<item |
|||
android:id="@+id/action_search" |
|||
android:orderInCategory="100" |
|||
android:title="Search" |
|||
android:icon="@drawable/search" |
|||
android:iconTint="@color/white" |
|||
app:showAsAction="always" /> |
|||
|
|||
<item |
|||
android:id="@+id/action_more" |
|||
android:orderInCategory="100" |
|||
android:title="More" |
|||
android:icon="@drawable/more" |
|||
android:iconTint="@color/white" |
|||
app:showAsAction="always" /> |
|||
|
|||
</menu> |
Loading…
Reference in new issue