mirror of
https://github.com/m2049r/xmrwallet
synced 2025-09-04 00:53:36 +02:00
Compare commits
21 Commits
v1.1.2-alp
...
v1.2.3
Author | SHA1 | Date | |
---|---|---|---|
![]() |
347123d961 | ||
![]() |
f5ad07c2b0 | ||
![]() |
62695af9c6 | ||
![]() |
3b1c3d564b | ||
![]() |
b28a140b48 | ||
![]() |
75bba4a091 | ||
![]() |
cfb3c23003 | ||
![]() |
2cb87bab8e | ||
![]() |
1ddc3d6b58 | ||
![]() |
2fa48d7441 | ||
![]() |
545367db90 | ||
![]() |
d67e02cbcb | ||
![]() |
d3beb7ca3f | ||
![]() |
f951e1a621 | ||
![]() |
0e187d3b20 | ||
![]() |
716b830b7b | ||
![]() |
4ac6a03d63 | ||
![]() |
7eb86ea618 | ||
![]() |
4cfd166ed7 | ||
![]() |
44f241f4ee | ||
![]() |
62b77fc987 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.DS_Store
|
||||
/app/release
|
||||
|
@@ -21,7 +21,6 @@ You may lose all your Moneroj if you use this App. Be cautious when spending on
|
||||
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
|
||||
|
||||
### TODO
|
||||
- review visibility of methods/classes
|
||||
- more sensible error dialogs
|
||||
|
||||
### Issues / Pitfalls
|
||||
|
@@ -8,8 +8,8 @@ android {
|
||||
applicationId "com.m2049r.xmrwallet"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 29
|
||||
versionName "1.1.2-alpha"
|
||||
versionCode 44
|
||||
versionName "1.2.3"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
|
BIN
app/src/main/ic_launcher-web.png
Normal file
BIN
app/src/main/ic_launcher-web.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 245 KiB |
@@ -33,6 +33,7 @@ import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.model.WalletManager;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
@@ -48,16 +49,16 @@ public class GenerateFragment extends Fragment {
|
||||
static final String TYPE_SEED = "seed";
|
||||
static final String TYPE_VIEWONLY = "view";
|
||||
|
||||
TextInputLayout etWalletName;
|
||||
TextInputLayout etWalletPassword;
|
||||
TextInputLayout etWalletAddress;
|
||||
TextInputLayout etWalletMnemonic;
|
||||
TextInputLayout etWalletViewKey;
|
||||
TextInputLayout etWalletSpendKey;
|
||||
TextInputLayout etWalletRestoreHeight;
|
||||
Button bGenerate;
|
||||
private TextInputLayout etWalletName;
|
||||
private TextInputLayout etWalletPassword;
|
||||
private TextInputLayout etWalletAddress;
|
||||
private TextInputLayout etWalletMnemonic;
|
||||
private TextInputLayout etWalletViewKey;
|
||||
private TextInputLayout etWalletSpendKey;
|
||||
private TextInputLayout etWalletRestoreHeight;
|
||||
private Button bGenerate;
|
||||
|
||||
String type = null;
|
||||
private String type = null;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
@@ -366,7 +367,25 @@ public class GenerateFragment extends Fragment {
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
Log.d(TAG, "onResume()");
|
||||
activityCallback.setTitle(getString(R.string.generate_title));
|
||||
activityCallback.setTitle(getString(R.string.generate_title) + " - " + getType());
|
||||
activityCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
||||
|
||||
}
|
||||
|
||||
String getType() {
|
||||
switch (type) {
|
||||
case TYPE_KEY:
|
||||
return getString(R.string.generate_wallet_type_key);
|
||||
case TYPE_NEW:
|
||||
return getString(R.string.generate_wallet_type_new);
|
||||
case TYPE_SEED:
|
||||
return getString(R.string.generate_wallet_type_seed);
|
||||
case TYPE_VIEWONLY:
|
||||
return getString(R.string.generate_wallet_type_view);
|
||||
default:
|
||||
Log.e(TAG, "unknown type " + type);
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
GenerateFragment.Listener activityCallback;
|
||||
@@ -379,6 +398,9 @@ public class GenerateFragment extends Fragment {
|
||||
void onGenerate(String name, String password, String address, String viewKey, String spendKey, long height);
|
||||
|
||||
void setTitle(String title);
|
||||
|
||||
void setToolbarButton(int type);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -400,7 +422,21 @@ public class GenerateFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.create_wallet_menu, menu);
|
||||
switch (type) {
|
||||
case TYPE_KEY:
|
||||
inflater.inflate(R.menu.create_wallet_keys, menu);
|
||||
break;
|
||||
case TYPE_NEW:
|
||||
inflater.inflate(R.menu.create_wallet_new, menu);
|
||||
break;
|
||||
case TYPE_SEED:
|
||||
inflater.inflate(R.menu.create_wallet_seed, menu);
|
||||
break;
|
||||
case TYPE_VIEWONLY:
|
||||
inflater.inflate(R.menu.create_wallet_view, menu);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
}
|
||||
|
@@ -103,18 +103,6 @@ public class GenerateReviewFragment extends Fragment {
|
||||
copyAddress();
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.bCopySeed).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
nocopy();
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.bCopySepndKey).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
nocopy();
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.bAdvancedInfo).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -305,5 +293,6 @@ public class GenerateReviewFragment extends Fragment {
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.wallet_details_menu, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
}
|
@@ -47,8 +47,10 @@ import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.m2049r.xmrwallet.dialog.AboutFragment;
|
||||
import com.m2049r.xmrwallet.dialog.HelpFragment;
|
||||
import com.m2049r.xmrwallet.dialog.LicensesFragment;
|
||||
import com.m2049r.xmrwallet.dialog.DonationFragment;
|
||||
import com.m2049r.xmrwallet.dialog.PrivacyFragment;
|
||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.model.WalletManager;
|
||||
@@ -73,9 +75,8 @@ public class LoginActivity extends AppCompatActivity
|
||||
private static final String GENERATE_STACK = "gen";
|
||||
|
||||
static final int DAEMON_TIMEOUT = 500; // deamon must respond in 500ms
|
||||
static final int DAEMON_DNS_TIMEOUT = 5000; // how long to wait for DNS resolver
|
||||
|
||||
Toolbar toolbar;
|
||||
private Toolbar toolbar;
|
||||
|
||||
@Override
|
||||
public void setToolbarButton(int type) {
|
||||
@@ -121,7 +122,8 @@ public class LoginActivity extends AppCompatActivity
|
||||
finish();
|
||||
break;
|
||||
case Toolbar.BUTTON_DONATE:
|
||||
Toast.makeText(LoginActivity.this, getString(R.string.label_donate), Toast.LENGTH_SHORT).show();
|
||||
DonationFragment.display(getSupportFragmentManager());
|
||||
break;
|
||||
case Toolbar.BUTTON_NONE:
|
||||
default:
|
||||
Log.e(TAG, "Button " + type + "pressed - how can this be?");
|
||||
@@ -130,7 +132,7 @@ public class LoginActivity extends AppCompatActivity
|
||||
});
|
||||
|
||||
if (Helper.getWritePermission(this)) {
|
||||
startLoginFragment();
|
||||
if (savedInstanceState == null) startLoginFragment();
|
||||
} else {
|
||||
Log.i(TAG, "Waiting for permissions");
|
||||
}
|
||||
@@ -251,7 +253,7 @@ public class LoginActivity extends AppCompatActivity
|
||||
|
||||
// copy + delete seems safer than rename because we call rollback easily
|
||||
boolean renameWallet(File walletFile, String newName) {
|
||||
if (copyWallet(walletFile, new File(walletFile.getParentFile(), newName), false)) {
|
||||
if (copyWallet(walletFile, new File(walletFile.getParentFile(), newName), false, true)) {
|
||||
deleteWallet(walletFile);
|
||||
return true;
|
||||
} else {
|
||||
@@ -356,7 +358,7 @@ public class LoginActivity extends AppCompatActivity
|
||||
// TODO probably better to copy to a new file and then rename
|
||||
// then if something fails we have the old backup at least
|
||||
// or just create a new backup every time and keep n old backups
|
||||
boolean success = copyWallet(walletFile, backupFile, true);
|
||||
boolean success = copyWallet(walletFile, backupFile, true, true);
|
||||
Log.d(TAG, "copyWallet is " + success);
|
||||
return success;
|
||||
}
|
||||
@@ -604,6 +606,8 @@ public class LoginActivity extends AppCompatActivity
|
||||
if (progressDialog != null) progressDialog.show();
|
||||
}
|
||||
}, delay);
|
||||
} else {
|
||||
progressDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -969,8 +973,8 @@ public class LoginActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
boolean copyWallet(File srcWallet, File dstWallet, boolean backupMode) {
|
||||
if (walletExists(dstWallet, true) && !backupMode) return false;
|
||||
boolean copyWallet(File srcWallet, File dstWallet, boolean overwrite, boolean ignoreCacheError) {
|
||||
if (walletExists(dstWallet, true) && !overwrite) return false;
|
||||
boolean success = false;
|
||||
File srcDir = srcWallet.getParentFile();
|
||||
String srcName = srcWallet.getName();
|
||||
@@ -980,8 +984,8 @@ public class LoginActivity extends AppCompatActivity
|
||||
try {
|
||||
copyFile(new File(srcDir, srcName), new File(dstDir, dstName));
|
||||
} catch (IOException ex) {
|
||||
Log.d(TAG, "CACHE " + backupMode);
|
||||
if (!backupMode) { // ignore cache backup error if backing up (can be resynced)
|
||||
Log.d(TAG, "CACHE " + ignoreCacheError);
|
||||
if (!ignoreCacheError) { // ignore cache backup error if backing up (can be resynced)
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
@@ -1049,14 +1053,29 @@ public class LoginActivity extends AppCompatActivity
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_create_help:
|
||||
HelpFragment.displayHelp(getSupportFragmentManager(), R.raw.help_create);
|
||||
case R.id.action_create_help_new:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_new);
|
||||
return true;
|
||||
case R.id.action_create_help_keys:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_keys);
|
||||
return true;
|
||||
case R.id.action_create_help_view:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_view);
|
||||
return true;
|
||||
case R.id.action_create_help_seed:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_create_seed);
|
||||
return true;
|
||||
case R.id.action_details_help:
|
||||
HelpFragment.displayHelp(getSupportFragmentManager(), R.raw.help_details);
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_details);
|
||||
return true;
|
||||
case R.id.action_lincense_info:
|
||||
LicensesFragment.displayLicensesFragment(getSupportFragmentManager());
|
||||
case R.id.action_license_info:
|
||||
AboutFragment.display(getSupportFragmentManager());
|
||||
return true;
|
||||
case R.id.action_help_list:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_list);
|
||||
return true;
|
||||
case R.id.action_privacy_policy:
|
||||
PrivacyFragment.display(getSupportFragmentManager());
|
||||
return true;
|
||||
case R.id.action_testnet:
|
||||
try {
|
||||
|
@@ -18,9 +18,7 @@ package com.m2049r.xmrwallet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
@@ -66,8 +64,8 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
List<WalletManager.WalletInfo> walletList = new ArrayList<>();
|
||||
List<WalletManager.WalletInfo> displayedList = new ArrayList<>();
|
||||
|
||||
ImageView ivGuntherWallets;
|
||||
EditText etDummy;
|
||||
ImageView ivGunther;
|
||||
DropDownEditText etDaemonAddress;
|
||||
ArrayAdapter<String> nodeAdapter;
|
||||
|
||||
@@ -134,8 +132,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
Log.d(TAG, "onCreateView");
|
||||
View view = inflater.inflate(R.layout.fragment_login, container, false);
|
||||
|
||||
ivGuntherWallets = (ImageView) view.findViewById(R.id.ivGuntherWallets);
|
||||
|
||||
ivGunther = (ImageView) view.findViewById(R.id.ivGunther);
|
||||
fabScreen = (FrameLayout) view.findViewById(R.id.fabScreen);
|
||||
fab = (FloatingActionButton) view.findViewById(R.id.fab);
|
||||
fabNew = (FloatingActionButton) view.findViewById(R.id.fabNew);
|
||||
@@ -148,6 +145,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
fabKeyL = (RelativeLayout) view.findViewById(R.id.fabKeyL);
|
||||
fabSeedL = (RelativeLayout) view.findViewById(R.id.fabSeedL);
|
||||
|
||||
fab_pulse = AnimationUtils.loadAnimation(getContext(), R.anim.fab_pulse);
|
||||
fab_open_screen = AnimationUtils.loadAnimation(getContext(), R.anim.fab_open_screen);
|
||||
fab_close_screen = AnimationUtils.loadAnimation(getContext(), R.anim.fab_close_screen);
|
||||
fab_open = AnimationUtils.loadAnimation(getContext(), R.anim.fab_open);
|
||||
@@ -213,25 +211,10 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
});
|
||||
|
||||
loadPrefs();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
void showGunther() {
|
||||
ivGuntherWallets.setImageResource(R.drawable.gunther_wallets);
|
||||
final AnimationDrawable guntherWalletsAnim = (AnimationDrawable) ivGuntherWallets.getDrawable();
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
guntherWalletsAnim.start();
|
||||
}
|
||||
}, getResources().getInteger(R.integer.gunther_wallets_delay));
|
||||
}
|
||||
|
||||
void normalGunther() {
|
||||
ivGuntherWallets.setImageResource(R.drawable.gunther_wallets_00);
|
||||
}
|
||||
|
||||
// Callbacks from WalletInfoAdapter
|
||||
@Override
|
||||
public void onInteraction(final View view, final WalletManager.WalletInfo infoItem) {
|
||||
@@ -288,10 +271,18 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
filterList();
|
||||
adapter.setInfos(displayedList);
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
// deal with Gunther & FAB animation
|
||||
if (displayedList.isEmpty()) {
|
||||
showGunther();
|
||||
fab.startAnimation(fab_pulse);
|
||||
if (ivGunther.getDrawable() == null) {
|
||||
ivGunther.setImageResource(R.drawable.gunther_desaturated);
|
||||
}
|
||||
} else {
|
||||
normalGunther();
|
||||
fab.clearAnimation();
|
||||
if (ivGunther.getDrawable() != null) {
|
||||
ivGunther.setImageDrawable(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +339,10 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
//private static final String PREF_TESTNET = "testnet";
|
||||
|
||||
private static final String PREF_DAEMONLIST_MAINNET =
|
||||
"node.moneroworld.com:18089;node.xmrbackb.one:18081;node.xmr.be:18081";
|
||||
"node.moneroworld.com:18089;node.xmrbackb.one;node.xmr.be";
|
||||
|
||||
private static final String PREF_DAEMONLIST_TESTNET =
|
||||
"testnet.xmrchain.net";
|
||||
|
||||
private NodeList daemonTestNet;
|
||||
private NodeList daemonMainNet;
|
||||
@@ -357,7 +351,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
SharedPreferences sharedPref = activityCallback.getPrefs();
|
||||
|
||||
daemonMainNet = new NodeList(sharedPref.getString(PREF_DAEMON_MAINNET, PREF_DAEMONLIST_MAINNET));
|
||||
daemonTestNet = new NodeList(sharedPref.getString(PREF_DAEMON_TESTNET, ""));
|
||||
daemonTestNet = new NodeList(sharedPref.getString(PREF_DAEMON_TESTNET, PREF_DAEMONLIST_TESTNET));
|
||||
setNet(isTestnet(), false);
|
||||
}
|
||||
|
||||
@@ -407,6 +401,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
||||
private FrameLayout fabScreen;
|
||||
private RelativeLayout fabNewL, fabViewL, fabKeyL, fabSeedL;
|
||||
private Animation fab_open, fab_close, rotate_forward, rotate_backward, fab_open_screen, fab_close_screen;
|
||||
private Animation fab_pulse;
|
||||
|
||||
public boolean isFabOpen() {
|
||||
return isFabOpen;
|
||||
|
@@ -59,15 +59,15 @@ import java.util.Map;
|
||||
public class ReceiveFragment extends Fragment {
|
||||
static final String TAG = "ReceiveFragment";
|
||||
|
||||
ProgressBar pbProgress;
|
||||
TextView tvAddress;
|
||||
TextInputLayout etPaymentId;
|
||||
ExchangeView evAmount;
|
||||
Button bPaymentId;
|
||||
Button bGenerate;
|
||||
ImageView qrCode;
|
||||
EditText etDummy;
|
||||
ImageButton bCopyAddress;
|
||||
private ProgressBar pbProgress;
|
||||
private TextView tvAddress;
|
||||
private TextInputLayout etPaymentId;
|
||||
private ExchangeView evAmount;
|
||||
private Button bPaymentId;
|
||||
private Button bGenerate;
|
||||
private ImageView qrCode;
|
||||
private EditText etDummy;
|
||||
private ImageButton bCopyAddress;
|
||||
|
||||
//String name;
|
||||
|
||||
@@ -112,21 +112,17 @@ public class ReceiveFragment extends Fragment {
|
||||
generateQr();
|
||||
}
|
||||
});
|
||||
/*
|
||||
evAmount.setOnAmountInvalidatedListener(new ExchangeView.OnAmountInvalidatedListener() {
|
||||
@Override
|
||||
public void onAmountInvalidated() {
|
||||
clearQR();
|
||||
}
|
||||
});
|
||||
|
||||
evAmount.setOnFailedExchangeListener(new ExchangeView.OnFailedExchangeListener() {
|
||||
@Override
|
||||
public void onFailedExchange() {
|
||||
Toast.makeText(getActivity(), getString(R.string.message_exchange_failed), Toast.LENGTH_LONG).show();
|
||||
if (isAdded()) {
|
||||
clearQR();
|
||||
Toast.makeText(getActivity(), getString(R.string.message_exchange_failed), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
etPaymentId.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
|
||||
@@ -373,7 +369,7 @@ public class ReceiveFragment extends Fragment {
|
||||
|
||||
private Bitmap getMoneroLogo() {
|
||||
if (logo == null) {
|
||||
logo = Helper.getBitmap(getContext(), R.drawable.ic_monero_qr);
|
||||
logo = Helper.getBitmap(getContext(), R.drawable.ic_monero_logo_b);
|
||||
}
|
||||
return logo;
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
||||
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
|
||||
static final String TAG = "ScannerFragment";
|
||||
|
||||
Listener activityCallback;
|
||||
private Listener activityCallback;
|
||||
|
||||
public interface Listener {
|
||||
boolean onAddressScanned(String uri);
|
||||
|
@@ -20,16 +20,22 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
@@ -43,7 +49,6 @@ import com.m2049r.xmrwallet.layout.Toolbar;
|
||||
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.model.WalletManager;
|
||||
import com.m2049r.xmrwallet.util.AsyncExchangeRate;
|
||||
import com.m2049r.xmrwallet.util.BarcodeData;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
import com.m2049r.xmrwallet.util.TxData;
|
||||
@@ -51,33 +56,30 @@ import com.m2049r.xmrwallet.util.TxData;
|
||||
public class SendFragment extends Fragment {
|
||||
static final String TAG = "SendFragment";
|
||||
|
||||
EditText etDummy;
|
||||
private EditText etDummy;
|
||||
|
||||
ScrollView scrollview;
|
||||
private ScrollView scrollview;
|
||||
|
||||
TextInputLayout etAddress;
|
||||
TextInputLayout etPaymentId;
|
||||
//TextInputLayout etAmount;
|
||||
ExchangeView evAmount;
|
||||
TextView tvAmountB;
|
||||
Spinner sCurrencyA;
|
||||
Spinner sCurrencyB;
|
||||
private TextInputLayout etAddress;
|
||||
private TextInputLayout etPaymentId;
|
||||
|
||||
Button bScan;
|
||||
Spinner sMixin;
|
||||
Spinner sPriority;
|
||||
Button bPrepareSend;
|
||||
Button bDispose;
|
||||
Button bPaymentId;
|
||||
LinearLayout llConfirmSend;
|
||||
TextView tvTxAmount;
|
||||
TextView tvTxFee;
|
||||
private ExchangeView evAmount;
|
||||
|
||||
private Button bScan;
|
||||
private Spinner sMixin;
|
||||
private Spinner sPriority;
|
||||
private Button bPrepareSend;
|
||||
private Button bDispose;
|
||||
private Button bPaymentId;
|
||||
private LinearLayout llConfirmSend;
|
||||
private TextView tvTxAmount;
|
||||
private TextView tvTxFee;
|
||||
//TextView tvTxDust;
|
||||
TextView tvTxTotal;
|
||||
EditText etNotes;
|
||||
Button bSend;
|
||||
Button bReallySend;
|
||||
ProgressBar pbProgress;
|
||||
private TextView tvTxTotal;
|
||||
private EditText etNotes;
|
||||
private Button bSend;
|
||||
private Button bReallySend;
|
||||
private ProgressBar pbProgress;
|
||||
|
||||
final static int Mixins[] = {4, 7, 12, 25}; // must match the layout XML
|
||||
final static PendingTransaction.Priority Priorities[] =
|
||||
@@ -102,9 +104,6 @@ public class SendFragment extends Fragment {
|
||||
etAddress = (TextInputLayout) view.findViewById(R.id.etAddress);
|
||||
etPaymentId = (TextInputLayout) view.findViewById(R.id.etPaymentId);
|
||||
evAmount = (ExchangeView) view.findViewById(R.id.evAmount);
|
||||
tvAmountB = (TextView) view.findViewById(R.id.tvAmountB);
|
||||
sCurrencyA = (Spinner) view.findViewById(R.id.sCurrencyA);
|
||||
sCurrencyB = (Spinner) view.findViewById(R.id.sCurrencyB);
|
||||
|
||||
bScan = (Button) view.findViewById(R.id.bScan);
|
||||
bPrepareSend = (Button) view.findViewById(R.id.bPrepareSend);
|
||||
@@ -140,15 +139,18 @@ public class SendFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
evAmount.setOnNewAmountListener(new ExchangeView.OnNewAmountListener() {
|
||||
etAddress.getEditText().addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void onNewAmount(String xmr) {
|
||||
if ((xmr != null)) {
|
||||
// stupid workaround to not show error on open of screen
|
||||
if ((checkAddressNoError() && checkAmountWithError()) || checkAmount()) {
|
||||
etPaymentId.requestFocus();
|
||||
}
|
||||
}
|
||||
public void afterTextChanged(Editable editable) {
|
||||
etAddress.setError(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
});
|
||||
|
||||
@@ -165,6 +167,21 @@ public class SendFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
etPaymentId.getEditText().addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
etPaymentId.setError(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
});
|
||||
|
||||
bPrepareSend.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -213,8 +230,8 @@ public class SendFragment extends Fragment {
|
||||
public void onClick(View v) {
|
||||
bSend.setEnabled(false);
|
||||
boolean testnet = WalletManager.getInstance().isTestNet();
|
||||
if (!testnet) {
|
||||
//send();
|
||||
if (testnet) {
|
||||
send();
|
||||
} else {
|
||||
etNotes.setEnabled(false);
|
||||
Handler handler = new Handler();
|
||||
@@ -243,6 +260,42 @@ public class SendFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
sMixin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(final AdapterView<?> parentView, View selectedItemView, int position, long id) {
|
||||
parentView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isAdded())
|
||||
((TextView) parentView.getChildAt(0)).setTextColor(getResources().getColor(R.color.moneroGray));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parentView) {
|
||||
// nothing (yet?)
|
||||
}
|
||||
});
|
||||
sPriority.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(final AdapterView<?> parentView, View selectedItemView, int position, long id) {
|
||||
parentView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isAdded())
|
||||
((TextView) parentView.getChildAt(0)).setTextColor(getResources().getColor(R.color.moneroGray));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parentView) {
|
||||
// nothing (yet?)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
etDummy.requestFocus();
|
||||
Helper.hideKeyboard(getActivity());
|
||||
|
||||
@@ -365,8 +418,6 @@ public class SendFragment extends Fragment {
|
||||
|
||||
BarcodeData popScannedData();
|
||||
|
||||
void onExchange(AsyncExchangeRate.Listener listener, String currencyA, String currencyB);
|
||||
|
||||
void setSubtitle(String subtitle);
|
||||
|
||||
void setToolbarButton(int type);
|
||||
@@ -469,4 +520,15 @@ public class SendFragment extends Fragment {
|
||||
pbProgress.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.send_menu, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
}
|
||||
|
@@ -57,17 +57,17 @@ public class TxFragment extends Fragment {
|
||||
TS_FORMATTER.setTimeZone(tz);
|
||||
}
|
||||
|
||||
TextView tvTxTimestamp;
|
||||
TextView tvTxId;
|
||||
TextView tvTxKey;
|
||||
TextView tvDestination;
|
||||
TextView tvTxPaymentId;
|
||||
TextView tvTxBlockheight;
|
||||
TextView tvTxAmount;
|
||||
TextView tvTxFee;
|
||||
TextView tvTxTransfers;
|
||||
TextView etTxNotes;
|
||||
Button bTxNotes;
|
||||
private TextView tvTxTimestamp;
|
||||
private TextView tvTxId;
|
||||
private TextView tvTxKey;
|
||||
private TextView tvDestination;
|
||||
private TextView tvTxPaymentId;
|
||||
private TextView tvTxBlockheight;
|
||||
private TextView tvTxAmount;
|
||||
private TextView tvTxFee;
|
||||
private TextView tvTxTransfers;
|
||||
private TextView etTxNotes;
|
||||
private Button bTxNotes;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
@@ -212,18 +212,20 @@ public class TxFragment extends Fragment {
|
||||
}
|
||||
String sign = (info.direction == TransactionInfo.Direction.Direction_In ? "+" : "-");
|
||||
|
||||
tvTxAmount.setText(sign + Wallet.getDisplayAmount(info.amount));
|
||||
long realAmount = info.amount;
|
||||
if (info.isPending) {
|
||||
realAmount = realAmount - info.fee;
|
||||
}
|
||||
tvTxAmount.setText(sign + Wallet.getDisplayAmount(realAmount));
|
||||
|
||||
if ((info.fee > 0)) {
|
||||
String fee = Wallet.getDisplayAmount(info.fee);
|
||||
if (info.isPending) {
|
||||
tvTxFee.setText(getString(R.string.tx_list_fee_pending, fee));
|
||||
} else {
|
||||
tvTxFee.setText(getString(R.string.tx_list_fee, fee));
|
||||
}
|
||||
tvTxFee.setText(getString(R.string.tx_list_fee, fee));
|
||||
} else {
|
||||
tvTxFee.setText(null);
|
||||
tvTxFee.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (info.isFailed) {
|
||||
tvTxAmount.setText(getString(R.string.tx_list_amount_failed, Wallet.getDisplayAmount(info.amount)));
|
||||
tvTxFee.setText(getString(R.string.tx_list_failed_text));
|
||||
|
@@ -36,13 +36,14 @@ import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.m2049r.xmrwallet.dialog.DonationFragment;
|
||||
import com.m2049r.xmrwallet.dialog.HelpFragment;
|
||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
||||
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||
import com.m2049r.xmrwallet.model.TransactionInfo;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.model.WalletManager;
|
||||
import com.m2049r.xmrwallet.service.WalletService;
|
||||
import com.m2049r.xmrwallet.util.AsyncExchangeRate;
|
||||
import com.m2049r.xmrwallet.util.BarcodeData;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
import com.m2049r.xmrwallet.util.TxData;
|
||||
@@ -60,7 +61,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
public static final String REQUEST_ID = "id";
|
||||
public static final String REQUEST_PW = "pw";
|
||||
|
||||
Toolbar toolbar;
|
||||
private Toolbar toolbar;
|
||||
|
||||
@Override
|
||||
public void setToolbarButton(int type) {
|
||||
@@ -154,11 +155,23 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
onWalletDetails();
|
||||
return true;
|
||||
case R.id.action_donate:
|
||||
onWalletDetails();
|
||||
DonationFragment.display(getSupportFragmentManager());
|
||||
return true;
|
||||
case R.id.action_share:
|
||||
onShareTxInfo();
|
||||
return true;
|
||||
case R.id.action_help_tx_info:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_tx_details);
|
||||
return true;
|
||||
case R.id.action_help_wallet:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_wallet);
|
||||
return true;
|
||||
case R.id.action_details_help:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_details);
|
||||
return true;
|
||||
case R.id.action_help_send:
|
||||
HelpFragment.display(getSupportFragmentManager(), R.string.help_send);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@@ -186,6 +199,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
public void onButton(int type) {
|
||||
switch (type) {
|
||||
case Toolbar.BUTTON_BACK:
|
||||
onDisposeRequest();
|
||||
onBackPressed();
|
||||
break;
|
||||
case Toolbar.BUTTON_CLOSE:
|
||||
@@ -209,7 +223,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
|
||||
Fragment walletFragment = new WalletFragment();
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.add(R.id.fragment_container, walletFragment).commit();
|
||||
.add(R.id.fragment_container, walletFragment, WalletFragment.TAG).commit();
|
||||
Log.d(TAG, "fragment added");
|
||||
|
||||
startWalletService();
|
||||
@@ -375,12 +389,12 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
Log.d(TAG, "onRefreshed()");
|
||||
try {
|
||||
final WalletFragment walletFragment = (WalletFragment)
|
||||
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
getSupportFragmentManager().findFragmentByTag(WalletFragment.TAG);
|
||||
if (wallet.isSynchronized()) {
|
||||
Log.d(TAG, "onRefreshed() synced");
|
||||
releaseWakeLock(); // the idea is to stay awake until synced
|
||||
if (!synced) {
|
||||
onProgress(null);
|
||||
if (!synced) { // first sync
|
||||
onProgress(-1);
|
||||
saveWallet(); // save on first sync
|
||||
synced = true;
|
||||
runOnUiThread(new Runnable() {
|
||||
@@ -433,6 +447,16 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
} else {
|
||||
haveWallet = true;
|
||||
invalidateOptionsMenu();
|
||||
|
||||
final WalletFragment walletFragment = (WalletFragment)
|
||||
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if (walletFragment != null) {
|
||||
walletFragment.onLoaded();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,10 +523,10 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
public void onProgress(final String text) {
|
||||
try {
|
||||
final WalletFragment walletFragment = (WalletFragment)
|
||||
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
getSupportFragmentManager().findFragmentByTag(WalletFragment.TAG);
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
walletFragment.onProgress(text);
|
||||
walletFragment.setProgress(text);
|
||||
}
|
||||
});
|
||||
} catch (ClassCastException ex) {
|
||||
@@ -516,10 +540,10 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
public void onProgress(final int n) {
|
||||
try {
|
||||
final WalletFragment walletFragment = (WalletFragment)
|
||||
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
getSupportFragmentManager().findFragmentByTag(WalletFragment.TAG);
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
walletFragment.onProgress(n);
|
||||
walletFragment.setProgress(n);
|
||||
}
|
||||
});
|
||||
} catch (ClassCastException ex) {
|
||||
@@ -781,9 +805,4 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
|
||||
replaceFragment(new ReceiveFragment(), null, extras);
|
||||
Log.d(TAG, "ReceiveFragment placed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExchange(AsyncExchangeRate.Listener listener, String currencyA, String currencyB) {
|
||||
new AsyncExchangeRate(listener).execute(currencyA, currencyB);
|
||||
}
|
||||
}
|
||||
|
@@ -49,20 +49,20 @@ import java.util.List;
|
||||
public class WalletFragment extends Fragment
|
||||
implements TransactionInfoAdapter.OnInteractionListener,
|
||||
AsyncExchangeRate.Listener {
|
||||
private static final String TAG = "WalletFragment";
|
||||
public static final String TAG = "WalletFragment";
|
||||
private TransactionInfoAdapter adapter;
|
||||
private NumberFormat formatter = NumberFormat.getInstance();
|
||||
|
||||
FrameLayout flExchange;
|
||||
TextView tvBalance;
|
||||
TextView tvUnconfirmedAmount;
|
||||
TextView tvProgress;
|
||||
ImageView ivSynced;
|
||||
ProgressBar pbProgress;
|
||||
Button bReceive;
|
||||
Button bSend;
|
||||
private FrameLayout flExchange;
|
||||
private TextView tvBalance;
|
||||
private TextView tvUnconfirmedAmount;
|
||||
private TextView tvProgress;
|
||||
private ImageView ivSynced;
|
||||
private ProgressBar pbProgress;
|
||||
private Button bReceive;
|
||||
private Button bSend;
|
||||
|
||||
Spinner sCurrency;
|
||||
private Spinner sCurrency;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -96,7 +96,7 @@ public class WalletFragment extends Fragment
|
||||
ivSynced = (ImageView) view.findViewById(R.id.ivSynced);
|
||||
|
||||
sCurrency = (Spinner) view.findViewById(R.id.sCurrency);
|
||||
sCurrency.setAdapter(ArrayAdapter.createFromResource(getContext(), R.array.currency, R.layout.item_spinner));
|
||||
sCurrency.setAdapter(ArrayAdapter.createFromResource(getContext(), R.array.currency, R.layout.item_spinner_balance));
|
||||
|
||||
bSend = (Button) view.findViewById(R.id.bSend);
|
||||
bReceive = (Button) view.findViewById(R.id.bReceive);
|
||||
@@ -244,27 +244,40 @@ public class WalletFragment extends Fragment
|
||||
}
|
||||
}
|
||||
|
||||
public void setProgressText(final String text) {
|
||||
tvProgress.setText(text);
|
||||
boolean walletLoaded = false;
|
||||
|
||||
public void onLoaded() {
|
||||
walletLoaded = true;
|
||||
showReceive();
|
||||
}
|
||||
|
||||
public void onProgress(final String text) {
|
||||
if (text != null) {
|
||||
setProgressText(text);
|
||||
pbProgress.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
pbProgress.setVisibility(View.INVISIBLE);
|
||||
setProgressText(getString(R.string.status_working));
|
||||
onProgress(-1);
|
||||
private void showReceive() {
|
||||
if (walletLoaded) {
|
||||
bReceive.setVisibility(View.VISIBLE);
|
||||
bReceive.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onProgress(final int n) {
|
||||
if (n >= 0) {
|
||||
private String syncText = null;
|
||||
|
||||
public void setProgress(final String text) {
|
||||
syncText = text;
|
||||
tvProgress.setText(text);
|
||||
}
|
||||
|
||||
private int syncProgress = -1;
|
||||
|
||||
public void setProgress(final int n) {
|
||||
syncProgress = n;
|
||||
if (n > 100) {
|
||||
pbProgress.setIndeterminate(true);
|
||||
pbProgress.setVisibility(View.VISIBLE);
|
||||
} else if (n >= 0) {
|
||||
pbProgress.setIndeterminate(false);
|
||||
pbProgress.setProgress(n);
|
||||
} else {
|
||||
pbProgress.setIndeterminate(true);
|
||||
pbProgress.setVisibility(View.VISIBLE);
|
||||
} else { // <0
|
||||
pbProgress.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +300,6 @@ public class WalletFragment extends Fragment
|
||||
Log.d(TAG, "updateStatus()");
|
||||
if (walletTitle == null) {
|
||||
setActivityTitle(wallet);
|
||||
onProgress(100); // of loading
|
||||
}
|
||||
long balance = wallet.getBalance();
|
||||
unlockedBalance = wallet.getUnlockedBalance();
|
||||
@@ -295,8 +307,6 @@ public class WalletFragment extends Fragment
|
||||
double amountXmr = Double.parseDouble(Helper.getDisplayAmount(balance - unlockedBalance)); // assume this cannot fail!
|
||||
String unconfirmed = Helper.getFormattedAmount(amountXmr, true);
|
||||
tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount, unconfirmed));
|
||||
//tvUnconfirmedAmount.setText(getResources().getString(R.string.xmr_unconfirmed_amount,
|
||||
// Helper.getDisplayAmount(balance - unlockedBalance, Helper.DISPLAY_DIGITS_SHORT)));
|
||||
String sync = "";
|
||||
if (!activityCallback.hasBoundService())
|
||||
throw new IllegalStateException("WalletService not bound.");
|
||||
@@ -305,21 +315,23 @@ public class WalletFragment extends Fragment
|
||||
long daemonHeight = activityCallback.getDaemonHeight();
|
||||
if (!wallet.isSynchronized()) {
|
||||
long n = daemonHeight - wallet.getBlockChainHeight();
|
||||
sync = formatter.format(n) + " " + getString(R.string.status_remaining);
|
||||
sync = getString(R.string.status_syncing) + " " + formatter.format(n) + " " + getString(R.string.status_remaining);
|
||||
if (firstBlock == 0) {
|
||||
firstBlock = wallet.getBlockChainHeight();
|
||||
}
|
||||
int x = 100 - Math.round(100f * n / (1f * daemonHeight - firstBlock));
|
||||
onProgress(getString(R.string.status_syncing) + " " + sync);
|
||||
if (x == 0) x = -1;
|
||||
onProgress(x);
|
||||
if (x == 0) x = 101; // indeterminate
|
||||
setProgress(x);
|
||||
ivSynced.setVisibility(View.GONE);
|
||||
} else {
|
||||
sync = getString(R.string.status_synced) + ": " + formatter.format(wallet.getBlockChainHeight());
|
||||
sync = getString(R.string.status_synced) + formatter.format(wallet.getBlockChainHeight());
|
||||
ivSynced.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
sync = getString(R.string.status_wallet_connecting);
|
||||
setProgress(101);
|
||||
}
|
||||
setProgressText(sync);
|
||||
setProgress(sync);
|
||||
// TODO show connected status somewhere
|
||||
}
|
||||
|
||||
@@ -373,5 +385,8 @@ public class WalletFragment extends Fragment
|
||||
Log.d(TAG, "onResume()");
|
||||
activityCallback.setTitle(walletTitle, walletSubtitle);
|
||||
activityCallback.setToolbarButton(Toolbar.BUTTON_CLOSE);
|
||||
setProgress(syncProgress);
|
||||
setProgress(syncText);
|
||||
showReceive();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.dialog;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.m2049r.xmrwallet.BuildConfig;
|
||||
import com.m2049r.xmrwallet.R;
|
||||
|
||||
public class AboutFragment extends DialogFragment {
|
||||
static final String TAG = "AboutFragment";
|
||||
|
||||
public static AboutFragment newInstance() {
|
||||
return new AboutFragment();
|
||||
}
|
||||
|
||||
public static void display(FragmentManager fm) {
|
||||
FragmentTransaction ft = fm.beginTransaction();
|
||||
Fragment prev = fm.findFragmentByTag(TAG);
|
||||
if (prev != null) {
|
||||
ft.remove(prev);
|
||||
}
|
||||
|
||||
AboutFragment.newInstance().show(ft, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_about, null);
|
||||
((TextView) view.findViewById(R.id.tvHelp)).setText(Html.fromHtml(getString(R.string.about_licenses)));
|
||||
((TextView) view.findViewById(R.id.tvVersion)).setText(getString(R.string.about_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setView(view);
|
||||
builder.setNegativeButton(R.string.about_close,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
return builder.create();
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.dialog;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.m2049r.xmrwallet.R;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
|
||||
public class DonationFragment extends DialogFragment {
|
||||
static final String TAG = "DonationFragment";
|
||||
|
||||
public static DonationFragment newInstance() {
|
||||
return new DonationFragment();
|
||||
}
|
||||
|
||||
public static void display(FragmentManager fm) {
|
||||
FragmentTransaction ft = fm.beginTransaction();
|
||||
Fragment prev = fm.findFragmentByTag(TAG);
|
||||
if (prev != null) {
|
||||
ft.remove(prev);
|
||||
}
|
||||
|
||||
DonationFragment.newInstance().show(ft, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_donation, null);
|
||||
|
||||
((TextView) view.findViewById(R.id.tvCredits)).setText(Html.fromHtml(getString(R.string.donation_credits)));
|
||||
|
||||
(view.findViewById(R.id.bCopyAddress)).
|
||||
setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_address),
|
||||
((TextView) view.findViewById(R.id.tvWalletAddress)).getText().toString());
|
||||
Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setView(view);
|
||||
builder.setNegativeButton(R.string.about_close,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
}
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Copyright 2013 Adam Speakman, m2049r
|
||||
* <p>
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -16,98 +16,57 @@
|
||||
|
||||
package com.m2049r.xmrwallet.dialog;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.util.Log;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.m2049r.xmrwallet.R;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* Based on LicensesFragment by Adam Speakman on 24/09/13.
|
||||
* http://speakman.net.nz
|
||||
*/
|
||||
public class HelpFragment extends DialogFragment {
|
||||
static final String TAG = "HelpFragment";
|
||||
private static final String FRAGMENT_TAG = "com.m2049r.xmrwallet.dialog.HelpFragment";
|
||||
private static final String HELP_ID = "HELP_ID";
|
||||
|
||||
private AsyncTask<Void, Void, String> loader;
|
||||
|
||||
public static HelpFragment newInstance(int helpResourceId) {
|
||||
HelpFragment fragment = new HelpFragment();
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(HELP_ID, helpResourceId);
|
||||
fragment.setArguments(bundle);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fm A fragment manager instance used to display this LicensesFragment.
|
||||
*/
|
||||
public static void displayHelp(FragmentManager fm, int helpResourceId) {
|
||||
public static void display(FragmentManager fm, int helpResourceId) {
|
||||
FragmentTransaction ft = fm.beginTransaction();
|
||||
Fragment prev = fm.findFragmentByTag(FRAGMENT_TAG);
|
||||
Fragment prev = fm.findFragmentByTag(TAG);
|
||||
if (prev != null) {
|
||||
ft.remove(prev);
|
||||
}
|
||||
|
||||
// Create and show the dialog.
|
||||
DialogFragment newFragment = HelpFragment.newInstance(helpResourceId);
|
||||
newFragment.show(ft, FRAGMENT_TAG);
|
||||
HelpFragment.newInstance(helpResourceId).show(ft, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_help, null);
|
||||
|
||||
int helpId = 0;
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
helpId = arguments.getInt(HELP_ID);
|
||||
}
|
||||
if (helpId > 0)
|
||||
loadHelp(helpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (loader != null) {
|
||||
loader.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private WebView webView;
|
||||
private ProgressBar progress;
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
View content = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_help, null);
|
||||
webView = (WebView) content.findViewById(R.id.helpFragmentWebView);
|
||||
progress = (ProgressBar) content.findViewById(R.id.helpFragmentProgress);
|
||||
((TextView) view.findViewById(R.id.tvHelp)).setText(Html.fromHtml(getString(helpId)));
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
|
||||
builder.setView(content);
|
||||
builder.setView(view);
|
||||
builder.setNegativeButton(R.string.about_close,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
@@ -115,47 +74,6 @@ public class HelpFragment extends DialogFragment {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private void loadHelp(final int helpResourceId) {
|
||||
// Load asynchronously in case of a very large file.
|
||||
loader = new AsyncTask<Void, Void, String>() {
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Void... params) {
|
||||
InputStream rawResource = getActivity().getResources().openRawResource(helpResourceId);
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(rawResource));
|
||||
|
||||
String line;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
sb.append("\n");
|
||||
}
|
||||
bufferedReader.close();
|
||||
} catch (IOException ex) {
|
||||
Log.e(TAG, ex.getLocalizedMessage());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String licensesBody) {
|
||||
super.onPostExecute(licensesBody);
|
||||
if (getActivity() == null || isCancelled()) {
|
||||
return;
|
||||
}
|
||||
progress.setVisibility(View.INVISIBLE);
|
||||
webView.setVisibility(View.VISIBLE);
|
||||
webView.loadDataWithBaseURL(null, licensesBody, "text/html", "utf-8", null);
|
||||
loader = null;
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}
|
||||
}
|
@@ -1,165 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013 Adam Speakman, m2049r
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.dialog;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.m2049r.xmrwallet.BuildConfig;
|
||||
import com.m2049r.xmrwallet.R;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* Created by Adam Speakman on 24/09/13.
|
||||
* http://speakman.net.nz
|
||||
*/
|
||||
public class LicensesFragment extends DialogFragment {
|
||||
static final String TAG = "LicensesFragment";
|
||||
int versionCode = BuildConfig.VERSION_CODE;
|
||||
String versionName = BuildConfig.VERSION_NAME;
|
||||
|
||||
private AsyncTask<Void, Void, String> mLicenseLoader;
|
||||
|
||||
private static final String FRAGMENT_TAG = "com.m2049r.xmrwalelt.dialog.LicensesFragment";
|
||||
|
||||
/**
|
||||
* Creates a new instance of LicensesFragment with no Close button.
|
||||
*
|
||||
* @return A new licenses fragment.
|
||||
*/
|
||||
public static LicensesFragment newInstance() {
|
||||
return new LicensesFragment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and displays a licenses fragment with no Close button. Requires
|
||||
* "/res/raw/licenses.html" and "/res/layout/licenses_fragment.xml" to be
|
||||
* present.
|
||||
*
|
||||
* @param fm A fragment manager instance used to display this LicensesFragment.
|
||||
*/
|
||||
public static void displayLicensesFragment(FragmentManager fm) {
|
||||
FragmentTransaction ft = fm.beginTransaction();
|
||||
Fragment prev = fm.findFragmentByTag(FRAGMENT_TAG);
|
||||
if (prev != null) {
|
||||
ft.remove(prev);
|
||||
}
|
||||
ft.addToBackStack(null);
|
||||
|
||||
// Create and show the dialog.
|
||||
DialogFragment newFragment = LicensesFragment.newInstance();
|
||||
newFragment.show(ft, FRAGMENT_TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
loadLicenses();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mLicenseLoader != null) {
|
||||
mLicenseLoader.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private WebView mWebView;
|
||||
private ProgressBar mIndeterminateProgress;
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
View content = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_licenses, null);
|
||||
mWebView = (WebView) content.findViewById(R.id.licensesFragmentWebView);
|
||||
mIndeterminateProgress = (ProgressBar) content.findViewById(R.id.licensesFragmentIndeterminateProgress);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
TextView text = (TextView) content.findViewById(R.id.licensesFragmentText);
|
||||
text.setText(getString(R.string.about_text, versionName, versionCode));
|
||||
|
||||
builder.setView(content);
|
||||
builder.setNegativeButton(R.string.about_close,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private void loadLicenses() {
|
||||
// Load asynchronously in case of a very large file.
|
||||
mLicenseLoader = new AsyncTask<Void, Void, String>() {
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Void... params) {
|
||||
InputStream rawResource = getActivity().getResources().openRawResource(R.raw.licenses);
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(rawResource));
|
||||
|
||||
String line;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
sb.append("\n");
|
||||
}
|
||||
bufferedReader.close();
|
||||
} catch (IOException ex) {
|
||||
Log.e(TAG, ex.getLocalizedMessage());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String licensesBody) {
|
||||
super.onPostExecute(licensesBody);
|
||||
if (getActivity() == null || isCancelled()) {
|
||||
return;
|
||||
}
|
||||
mIndeterminateProgress.setVisibility(View.INVISIBLE);
|
||||
mWebView.setVisibility(View.VISIBLE);
|
||||
mWebView.loadDataWithBaseURL(null, licensesBody, "text/html", "utf-8", null);
|
||||
mLicenseLoader = null;
|
||||
}
|
||||
|
||||
}.execute();
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2017 m2049r
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.m2049r.xmrwallet.dialog;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.m2049r.xmrwallet.R;
|
||||
|
||||
public class PrivacyFragment extends DialogFragment {
|
||||
static final String TAG = "PrivacyFragment";
|
||||
|
||||
public static PrivacyFragment newInstance() {
|
||||
return new PrivacyFragment();
|
||||
}
|
||||
|
||||
public static void display(FragmentManager fm) {
|
||||
FragmentTransaction ft = fm.beginTransaction();
|
||||
Fragment prev = fm.findFragmentByTag(TAG);
|
||||
if (prev != null) {
|
||||
ft.remove(prev);
|
||||
}
|
||||
|
||||
PrivacyFragment.newInstance().show(ft, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_privacy_policy, null);
|
||||
|
||||
((TextView) view.findViewById(R.id.tvCredits)).setText(Html.fromHtml(getString(R.string.privacy_policy)));
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setView(view);
|
||||
builder.setNegativeButton(R.string.about_close,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
return builder.create();
|
||||
}
|
||||
}
|
@@ -67,6 +67,7 @@ public class ExchangeView extends LinearLayout implements AsyncExchangeRate.List
|
||||
public void setAmount(String xmrAmount) {
|
||||
if (xmrAmount != null) {
|
||||
setCurrencyA(0);
|
||||
etAmount.getEditText().setText(xmrAmount);
|
||||
setXmr(xmrAmount);
|
||||
this.notXmrAmount = null;
|
||||
doExchange();
|
||||
@@ -178,10 +179,16 @@ public class ExchangeView extends LinearLayout implements AsyncExchangeRate.List
|
||||
|
||||
sCurrencyB.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
|
||||
public void onItemSelected(final AdapterView<?> parentView, View selectedItemView, int position, long id) {
|
||||
if (position != 0) { // if not XMR, select XMR on other
|
||||
sCurrencyA.setSelection(0, true);
|
||||
}
|
||||
parentView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
((TextView) parentView.getChildAt(0)).setTextColor(getResources().getColor(R.color.moneroGray));
|
||||
}
|
||||
});
|
||||
doExchange();
|
||||
}
|
||||
|
||||
@@ -191,6 +198,15 @@ public class ExchangeView extends LinearLayout implements AsyncExchangeRate.List
|
||||
}
|
||||
});
|
||||
|
||||
etAmount.getEditText().setOnFocusChangeListener(new OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (!hasFocus) {
|
||||
doExchange();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
etAmount.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
|
||||
@@ -255,10 +271,6 @@ public class ExchangeView extends LinearLayout implements AsyncExchangeRate.List
|
||||
return ok;
|
||||
}
|
||||
|
||||
int selectedNotXmrCurrency() {
|
||||
return Math.max(getCurrencyA(), getCurrencyB());
|
||||
}
|
||||
|
||||
public void doExchange() {
|
||||
tvAmountB.setText("--");
|
||||
// TODO cache & use cached exchange rate here
|
||||
@@ -274,6 +286,7 @@ public class ExchangeView extends LinearLayout implements AsyncExchangeRate.List
|
||||
|
||||
public void exchange(double rate) {
|
||||
if (getCurrencyA() == 0) {
|
||||
if (xmrAmount == null) return;
|
||||
if (!xmrAmount.isEmpty() && (rate > 0)) {
|
||||
double amountB = rate * Double.parseDouble(xmrAmount);
|
||||
notXmrAmount = Helper.getFormattedAmount(amountB, getCurrencyB() == 0);
|
||||
@@ -282,6 +295,7 @@ public class ExchangeView extends LinearLayout implements AsyncExchangeRate.List
|
||||
}
|
||||
tvAmountB.setText(notXmrAmount);
|
||||
} else if (getCurrencyB() == 0) {
|
||||
if (notXmrAmount == null) return;
|
||||
if (!notXmrAmount.isEmpty() && (rate > 0)) {
|
||||
double amountB = rate * Double.parseDouble(notXmrAmount);
|
||||
setXmr(Helper.getFormattedAmount(amountB, true));
|
||||
@@ -339,7 +353,9 @@ public class ExchangeView extends LinearLayout implements AsyncExchangeRate.List
|
||||
public void exchangeFailed() {
|
||||
hideProgress();
|
||||
exchange(0);
|
||||
// TODO Toast it failed - I think this happens elsewhere already
|
||||
if (onFailedExchangeListener != null) {
|
||||
onFailedExchangeListener.onFailedExchange();
|
||||
}
|
||||
}
|
||||
|
||||
// callback from AsyncExchangeRate when we have a rate
|
||||
|
@@ -19,6 +19,7 @@
|
||||
package com.m2049r.xmrwallet.layout;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -79,6 +80,12 @@ public class Toolbar extends android.support.v7.widget.Toolbar {
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
toolbarImage = (ImageView) findViewById(R.id.toolbarImage);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
// the vector image does not work well for androis < Nougat
|
||||
toolbarImage.getLayoutParams().width = (int) getResources().getDimension(R.dimen.logo_width);
|
||||
toolbarImage.setImageResource(R.drawable.logo_horizontol_xmrujo);
|
||||
}
|
||||
|
||||
toolbarTitle = (TextView) findViewById(R.id.toolbarTitle);
|
||||
toolbarSubtitle = (TextView) findViewById(R.id.toolbarSubtitle);
|
||||
bDonate = (Button) findViewById(R.id.bDonate);
|
||||
|
@@ -47,10 +47,10 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
||||
//static final int TX_PENDING = Color.rgb(72, 53, 176);
|
||||
//static final int TX_FAILED = Color.rgb(208, 0, 255);
|
||||
|
||||
int outboundColour;
|
||||
int inboundColour;
|
||||
int pendingColour;
|
||||
int failedColour;
|
||||
private int outboundColour;
|
||||
private int inboundColour;
|
||||
private int pendingColour;
|
||||
private int failedColour;
|
||||
|
||||
public interface OnInteractionListener {
|
||||
void onInteraction(View view, TransactionInfo item);
|
||||
@@ -59,7 +59,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
||||
private final List<TransactionInfo> infoItems;
|
||||
private final OnInteractionListener listener;
|
||||
|
||||
Context context;
|
||||
private Context context;
|
||||
|
||||
public TransactionInfoAdapter(Context context, OnInteractionListener listener) {
|
||||
this.context = context;
|
||||
|
@@ -31,9 +31,9 @@ import android.os.Process;
|
||||
public class MoneroHandlerThread extends Thread {
|
||||
// from src/cryptonote_config.h
|
||||
static public final long THREAD_STACK_SIZE = 5 * 1024 * 1024;
|
||||
int mPriority;
|
||||
int mTid = -1;
|
||||
Looper mLooper;
|
||||
private int mPriority;
|
||||
private int mTid = -1;
|
||||
private Looper mLooper;
|
||||
|
||||
public MoneroHandlerThread(String name) {
|
||||
super(null, null, name, THREAD_STACK_SIZE);
|
||||
@@ -47,7 +47,7 @@ public class MoneroHandlerThread extends Thread {
|
||||
* @param priority The priority to run the thread at. The value supplied must be from
|
||||
* {@link android.os.Process} and not from java.lang.Thread.
|
||||
*/
|
||||
public MoneroHandlerThread(String name, int priority) {
|
||||
MoneroHandlerThread(String name, int priority) {
|
||||
super(null, null, name, THREAD_STACK_SIZE);
|
||||
mPriority = priority;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public class MoneroHandlerThread extends Thread {
|
||||
* setup before Looper loops.
|
||||
*/
|
||||
|
||||
protected void onLooperPrepared() {
|
||||
private void onLooperPrepared() {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,7 +81,7 @@ public class MoneroHandlerThread extends Thread {
|
||||
*
|
||||
* @return The looper.
|
||||
*/
|
||||
public Looper getLooper() {
|
||||
Looper getLooper() {
|
||||
if (!isAlive()) {
|
||||
return null;
|
||||
}
|
||||
|
@@ -254,7 +254,6 @@ public class WalletService extends Service {
|
||||
/////////////////////////////////////////////
|
||||
/////////////////////////////////////////////
|
||||
|
||||
private Looper mServiceLooper;
|
||||
private WalletService.ServiceHandler mServiceHandler;
|
||||
|
||||
private boolean errorState = false;
|
||||
@@ -334,7 +333,8 @@ public class WalletService extends Service {
|
||||
Wallet myWallet = getWallet();
|
||||
Log.d(TAG, "SEND TX for wallet: " + myWallet.getName());
|
||||
PendingTransaction pendingTransaction = myWallet.getPendingTransaction();
|
||||
if (pendingTransaction.getStatus() != PendingTransaction.Status.Status_Ok) {
|
||||
if ((pendingTransaction == null)
|
||||
|| (pendingTransaction.getStatus() != PendingTransaction.Status.Status_Ok)) {
|
||||
Log.e(TAG, "PendingTransaction is " + pendingTransaction.getStatus());
|
||||
myWallet.disposePendingTransaction(); // it's broken anyway
|
||||
if (observer != null) observer.onSentTransaction(false);
|
||||
@@ -398,8 +398,8 @@ public class WalletService extends Service {
|
||||
thread.start();
|
||||
|
||||
// Get the HandlerThread's Looper and use it for our Handler
|
||||
mServiceLooper = thread.getLooper();
|
||||
mServiceHandler = new WalletService.ServiceHandler(mServiceLooper);
|
||||
final Looper serviceLooper = thread.getLooper();
|
||||
mServiceHandler = new WalletService.ServiceHandler(serviceLooper);
|
||||
|
||||
Log.d(TAG, "Service created");
|
||||
}
|
||||
@@ -481,7 +481,7 @@ public class WalletService extends Service {
|
||||
showProgress(100);
|
||||
}
|
||||
showProgress(getString(R.string.status_wallet_connecting));
|
||||
showProgress(-1);
|
||||
showProgress(101);
|
||||
// if we try to refresh the history here we get occasional segfaults!
|
||||
// doesnt matter since we update as soon as we get a new block anyway
|
||||
Log.d(TAG, "start() done");
|
||||
|
@@ -24,19 +24,19 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class AsyncExchangeRate extends AsyncTask<String, Void, Boolean> {
|
||||
static final String TAG = "AsyncGetExchangeRate";
|
||||
private static final String TAG = "AsyncGetExchangeRate";
|
||||
|
||||
static final long TIME_REFRESH_INTERVAL = 60000; // refresh exchange rate max every minute
|
||||
private static final long TIME_REFRESH_INTERVAL = 60000; // refresh exchange rate max every minute
|
||||
|
||||
static protected long RateTime = 0;
|
||||
static protected double Rate = 0;
|
||||
static protected String Fiat = null;
|
||||
private static long RateTime = 0;
|
||||
private static double Rate = 0;
|
||||
private static String Fiat = null;
|
||||
|
||||
public interface Listener {
|
||||
void exchange(String currencyA, String currencyB, double rate);
|
||||
}
|
||||
|
||||
Listener listener;
|
||||
private Listener listener;
|
||||
|
||||
public AsyncExchangeRate(Listener listener) {
|
||||
super();
|
||||
@@ -49,9 +49,9 @@ public class AsyncExchangeRate extends AsyncTask<String, Void, Boolean> {
|
||||
super.onPreExecute();
|
||||
}
|
||||
|
||||
boolean inverse = false;
|
||||
String currencyA = null;
|
||||
String currencyB = null;
|
||||
private boolean inverse = false;
|
||||
private String currencyA = null;
|
||||
private String currencyB = null;
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params) {
|
||||
@@ -125,7 +125,7 @@ public class AsyncExchangeRate extends AsyncTask<String, Void, Boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
String getExchangeRate(String fiat) {
|
||||
private String getExchangeRate(String fiat) {
|
||||
String jsonResponse =
|
||||
Helper.getUrl("https://api.kraken.com/0/public/Ticker?pair=XMR" + fiat);
|
||||
if (jsonResponse == null) return null;
|
||||
|
@@ -118,7 +118,7 @@ public class Helper {
|
||||
}
|
||||
|
||||
/* Checks if external storage is available for read and write */
|
||||
static public boolean isExternalStorageWritable() {
|
||||
private static boolean isExternalStorageWritable() {
|
||||
String state = Environment.getExternalStorageState();
|
||||
return Environment.MEDIA_MOUNTED.equals(state);
|
||||
}
|
||||
@@ -156,7 +156,7 @@ public class Helper {
|
||||
}
|
||||
|
||||
// amountString must have '.' as decimal point
|
||||
static public String getDisplayAmount(String amountString, int maxDecimals) {
|
||||
private static String getDisplayAmount(String amountString, int maxDecimals) {
|
||||
int lastZero = 0;
|
||||
int decimal = 0;
|
||||
for (int i = amountString.length() - 1; i >= 0; i--) {
|
||||
|
@@ -22,9 +22,9 @@ import java.util.List;
|
||||
|
||||
public class NodeList {
|
||||
static private final String TAG = "NodeList";
|
||||
static public final int MAX_SIZE = 5;
|
||||
private static final int MAX_SIZE = 5;
|
||||
|
||||
List<String> nodes = new ArrayList<>();
|
||||
private List<String> nodes = new ArrayList<>();
|
||||
|
||||
public List<String> getNodes() {
|
||||
return nodes;
|
||||
|
15
app/src/main/res/anim/fab_pulse.xml
Normal file
15
app/src/main/res/anim/fab_pulse.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fillAfter="true">
|
||||
<scale
|
||||
android:duration="500"
|
||||
android:fromXScale="1.0"
|
||||
android:fromYScale="1.0"
|
||||
android:interpolator="@android:anim/linear_interpolator"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:repeatCount="infinite"
|
||||
android:repeatMode="reverse"
|
||||
android:toXScale="2.0"
|
||||
android:toYScale="2.0" />
|
||||
</set>
|
12
app/src/main/res/drawable/backgound_spinner_gray.xml
Normal file
12
app/src/main/res/drawable/backgound_spinner_gray.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">
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="8dp"
|
||||
android:right="8dp"
|
||||
android:top="8dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/moneroGray" />
|
||||
</shape>
|
BIN
app/src/main/res/drawable/gunther_desaturated.png
Normal file
BIN
app/src/main/res/drawable/gunther_desaturated.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
app/src/main/res/drawable/gunther_donate.png
Normal file
BIN
app/src/main/res/drawable/gunther_donate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
@@ -1,73 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:oneshot="true">
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_00"
|
||||
android:duration="500" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_01"
|
||||
android:duration="200" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_02"
|
||||
android:duration="2000" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_03"
|
||||
android:duration="1000" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_04"
|
||||
android:duration="100" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_05"
|
||||
android:duration="1000" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_06"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_07"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_08"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_09"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_10"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_11"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_12"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_13"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_14"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_15"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_16"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_17"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_18"
|
||||
android:duration="5000" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_19"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_20"
|
||||
android:duration="0" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_21"
|
||||
android:duration="100" />
|
||||
<item
|
||||
android:drawable="@drawable/gunther_wallets_22"
|
||||
android:duration="200" />
|
||||
</animation-list>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user