mirror of
https://github.com/m2049r/xmrwallet
synced 2025-09-07 11:35:59 +02:00
Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
bafe05117b | ||
![]() |
4b7c181040 | ||
![]() |
a3721ae784 | ||
![]() |
ae62c528aa | ||
![]() |
e6522769d0 | ||
![]() |
cab93e8c5e | ||
![]() |
ac78ecb298 | ||
![]() |
51876f788f | ||
![]() |
82c32d4442 | ||
![]() |
22b4905828 | ||
![]() |
0cb8ece336 | ||
![]() |
d2429da044 | ||
![]() |
92d867fbaa | ||
![]() |
a5e3986eb9 | ||
![]() |
8f7f4ee9f9 | ||
![]() |
c23597066a | ||
![]() |
dab5e08910 | ||
![]() |
c35deab283 | ||
![]() |
7c36ccfd9c | ||
![]() |
402d51ec6e | ||
![]() |
ca58211676 | ||
![]() |
97c6ba5334 | ||
![]() |
f1f2f250be | ||
![]() |
7b19e9a2bd | ||
![]() |
ed8010c92c | ||
![]() |
41580e5519 | ||
![]() |
1875e2df62 | ||
![]() |
347123d961 | ||
![]() |
f5ad07c2b0 | ||
![]() |
62695af9c6 | ||
![]() |
3b1c3d564b | ||
![]() |
b28a140b48 | ||
![]() |
75bba4a091 | ||
![]() |
cfb3c23003 |
@@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "com.m2049r.xmrwallet"
|
applicationId "com.m2049r.xmrwallet"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
versionCode 38
|
versionCode 51
|
||||||
versionName "1.1.7"
|
versionName "1.2.11"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
@@ -43,28 +43,39 @@ dependencies {
|
|||||||
compile 'com.android.support:cardview-v7:25.4.0'
|
compile 'com.android.support:cardview-v7:25.4.0'
|
||||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||||
compile 'me.dm7.barcodescanner:zxing:1.9.8'
|
compile 'me.dm7.barcodescanner:zxing:1.9.8'
|
||||||
|
|
||||||
|
compile "com.squareup.okhttp3:okhttp:$rootProject.ext.okHttpVersion"
|
||||||
|
compile "com.jakewharton.timber:timber:$rootProject.ext.timberVersion"
|
||||||
|
|
||||||
|
testCompile "junit:junit:$rootProject.ext.junitVersion"
|
||||||
|
testCompile "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"
|
||||||
|
testCompile "com.squareup.okhttp3:mockwebserver:$rootProject.ext.okHttpVersion"
|
||||||
|
testCompile 'org.json:json:20140107'
|
||||||
|
testCompile 'net.jodah:concurrentunit:0.4.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'com.android.support:appcompat-v7:70551e62660db15b790c5275f56b9de4dd9407d1494d07c8f3dd5698f3638677',
|
|
||||||
'com.android.support:design:3f409bf2019967ffc344cfaf11e52131fac982468a1707aaeb25bf3c52838966',
|
'com.android.support:design:3f409bf2019967ffc344cfaf11e52131fac982468a1707aaeb25bf3c52838966',
|
||||||
|
'com.android.support:appcompat-v7:70551e62660db15b790c5275f56b9de4dd9407d1494d07c8f3dd5698f3638677',
|
||||||
|
'com.android.support:transition:848270144fb180efd2bf928a00ed176dbbc5290badfd638390ffba90088df8b3',
|
||||||
|
'me.dm7.barcodescanner:zxing:d43973c9527c23fa8e6d338c6a2c458e373ce1ac6bcaa3bc41d11ae49116000d',
|
||||||
|
'me.dm7.barcodescanner:core:a5c8a704089b58029db166172ed8e55d756877d010a85a0b1c94fdc96ffb8f9a',
|
||||||
'com.android.support:support-v4:ee44c481a1f4d6978568e223e8125379b52b2ececdd53450e09ebae144bd377d',
|
'com.android.support:support-v4:ee44c481a1f4d6978568e223e8125379b52b2ececdd53450e09ebae144bd377d',
|
||||||
'com.android.support:recyclerview-v7:a2fe121f9d01ed8980e97095b4a3fe9700a0aa0a7d4b0f8c594f765ad8455a0d',
|
'com.android.support:recyclerview-v7:a2fe121f9d01ed8980e97095b4a3fe9700a0aa0a7d4b0f8c594f765ad8455a0d',
|
||||||
'com.android.support:cardview-v7:f3fbbe1fcfdbec7333c6a2c516c5fd511a909d1975271818e268d6fe297d8c70',
|
'com.android.support:cardview-v7:f3fbbe1fcfdbec7333c6a2c516c5fd511a909d1975271818e268d6fe297d8c70',
|
||||||
'com.android.support.constraint:constraint-layout:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085',
|
'com.android.support.constraint:constraint-layout:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085',
|
||||||
'me.dm7.barcodescanner:zxing:d43973c9527c23fa8e6d338c6a2c458e373ce1ac6bcaa3bc41d11ae49116000d',
|
|
||||||
'com.android.support:support-annotations:a774272036941b4e912eb426d70c848bde7f06a3bf5fb491f75a427dc6595270',
|
|
||||||
'com.android.support:support-vector-drawable:077009d13882ee96f061e4bc2dbe7cce7ae1762d8297592a787ff741afbfb1f2',
|
|
||||||
'com.android.support:animated-vector-drawable:628ab1d56a6ee4cbedf32617af8b2a1fe02964ed0628e8f898cc09ddba6e1835',
|
'com.android.support:animated-vector-drawable:628ab1d56a6ee4cbedf32617af8b2a1fe02964ed0628e8f898cc09ddba6e1835',
|
||||||
'com.android.support:transition:848270144fb180efd2bf928a00ed176dbbc5290badfd638390ffba90088df8b3',
|
'com.android.support:support-vector-drawable:077009d13882ee96f061e4bc2dbe7cce7ae1762d8297592a787ff741afbfb1f2',
|
||||||
'com.android.support:support-compat:54019c63614ce08b02d7b9605490cd2b29ba5b2505f394a9517450b5f72b30ca',
|
'com.android.support:support-fragment:316d35d4d2d2902057efad104a73e4bdb50bee260a7075678185b8cd71170945',
|
||||||
|
'com.android.support:support-core-ui:e72ae29b823889686cff6fcb948d6745c2baf6d4c2af4fdffa1ec1e42e3833a3',
|
||||||
'com.android.support:support-media-compat:566a161d9cb0083ef62a53e46b71ce5b3d455b8635b1a0a4ae28d96d4b583de8',
|
'com.android.support:support-media-compat:566a161d9cb0083ef62a53e46b71ce5b3d455b8635b1a0a4ae28d96d4b583de8',
|
||||||
'com.android.support:support-core-utils:34b8437dfa95ff28d29cf57ffa3b1354a9fa9bfe4059f0fd5ce2f5e4326a1748',
|
'com.android.support:support-core-utils:34b8437dfa95ff28d29cf57ffa3b1354a9fa9bfe4059f0fd5ce2f5e4326a1748',
|
||||||
'com.android.support:support-core-ui:e72ae29b823889686cff6fcb948d6745c2baf6d4c2af4fdffa1ec1e42e3833a3',
|
'com.android.support:support-compat:54019c63614ce08b02d7b9605490cd2b29ba5b2505f394a9517450b5f72b30ca',
|
||||||
'com.android.support:support-fragment:316d35d4d2d2902057efad104a73e4bdb50bee260a7075678185b8cd71170945',
|
'com.android.support:support-annotations:a774272036941b4e912eb426d70c848bde7f06a3bf5fb491f75a427dc6595270',
|
||||||
'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
|
'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
|
||||||
'me.dm7.barcodescanner:core:a5c8a704089b58029db166172ed8e55d756877d010a85a0b1c94fdc96ffb8f9a',
|
|
||||||
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
|
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
|
||||||
|
'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
|
||||||
|
'com.squareup.okhttp3:okhttp:7265adbd6f028aade307f58569d814835cd02bc9beffb70c25f72c9de50d61c4',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
|
android:name=".XmrWalletApplication"
|
||||||
android:theme="@style/MyMaterialTheme">
|
android:theme="@style/MyMaterialTheme">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
@@ -22,7 +22,6 @@ import android.support.annotation.Nullable;
|
|||||||
import android.support.design.widget.TextInputLayout;
|
import android.support.design.widget.TextInputLayout;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -33,15 +32,16 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class GenerateFragment extends Fragment {
|
public class GenerateFragment extends Fragment {
|
||||||
static final String TAG = "GenerateFragment";
|
|
||||||
|
|
||||||
static final String TYPE = "type";
|
static final String TYPE = "type";
|
||||||
static final String TYPE_NEW = "new";
|
static final String TYPE_NEW = "new";
|
||||||
@@ -366,7 +366,7 @@ public class GenerateFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Timber.d("onResume()");
|
||||||
activityCallback.setTitle(getString(R.string.generate_title) + " - " + getType());
|
activityCallback.setTitle(getString(R.string.generate_title) + " - " + getType());
|
||||||
activityCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
activityCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
||||||
|
|
||||||
@@ -383,7 +383,7 @@ public class GenerateFragment extends Fragment {
|
|||||||
case TYPE_VIEWONLY:
|
case TYPE_VIEWONLY:
|
||||||
return getString(R.string.generate_wallet_type_view);
|
return getString(R.string.generate_wallet_type_view);
|
||||||
default:
|
default:
|
||||||
Log.e(TAG, "unknown type " + type);
|
Timber.e("unknown type %s", type);
|
||||||
return "?";
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,6 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -35,14 +34,15 @@ import android.widget.ScrollView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class GenerateReviewFragment extends Fragment {
|
public class GenerateReviewFragment extends Fragment {
|
||||||
static final String TAG = "GenerateReviewFragment";
|
|
||||||
static final public String VIEW_TYPE_DETAILS = "details";
|
static final public String VIEW_TYPE_DETAILS = "details";
|
||||||
static final public String VIEW_TYPE_ACCEPT = "accept";
|
static final public String VIEW_TYPE_ACCEPT = "accept";
|
||||||
static final public String VIEW_TYPE_WALLET = "wallet";
|
static final public String VIEW_TYPE_WALLET = "wallet";
|
||||||
@@ -264,7 +264,7 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Timber.d("onResume()");
|
||||||
String name = tvWalletName.getText().toString();
|
String name = tvWalletName.getText().toString();
|
||||||
if (name.isEmpty()) name = null;
|
if (name.isEmpty()) name = null;
|
||||||
activityCallback.setTitle(name, getString(R.string.details_title));
|
activityCallback.setTitle(name, getString(R.string.details_title));
|
||||||
@@ -293,5 +293,6 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.wallet_details_menu, menu);
|
inflater.inflate(R.menu.wallet_details_menu, menu);
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,6 @@ import android.support.annotation.Nullable;
|
|||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -44,20 +43,21 @@ import android.widget.RelativeLayout;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.layout.DropDownEditText;
|
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
|
||||||
import com.m2049r.xmrwallet.layout.WalletInfoAdapter;
|
import com.m2049r.xmrwallet.layout.WalletInfoAdapter;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.NodeList;
|
import com.m2049r.xmrwallet.util.NodeList;
|
||||||
|
import com.m2049r.xmrwallet.widget.DropDownEditText;
|
||||||
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInteractionListener,
|
public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInteractionListener,
|
||||||
View.OnClickListener {
|
View.OnClickListener {
|
||||||
private static final String TAG = "LoginFragment";
|
|
||||||
|
|
||||||
private WalletInfoAdapter adapter;
|
private WalletInfoAdapter adapter;
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
Log.d(TAG, "onPause()");
|
Timber.d("onPause()");
|
||||||
savePrefs();
|
savePrefs();
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Timber.d("onResume()");
|
||||||
activityCallback.setTitle(null);
|
activityCallback.setTitle(null);
|
||||||
activityCallback.setToolbarButton(Toolbar.BUTTON_DONATE);
|
activityCallback.setToolbarButton(Toolbar.BUTTON_DONATE);
|
||||||
activityCallback.showNet(isTestnet());
|
activityCallback.showNet(isTestnet());
|
||||||
@@ -129,7 +129,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
Log.d(TAG, "onCreateView");
|
Timber.d("onCreateView");
|
||||||
View view = inflater.inflate(R.layout.fragment_login, container, false);
|
View view = inflater.inflate(R.layout.fragment_login, container, false);
|
||||||
|
|
||||||
ivGunther = (ImageView) view.findViewById(R.id.ivGunther);
|
ivGunther = (ImageView) view.findViewById(R.id.ivGunther);
|
||||||
@@ -262,7 +262,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadList() {
|
public void loadList() {
|
||||||
Log.d(TAG, "loadList()");
|
Timber.d("loadList()");
|
||||||
WalletManager mgr = WalletManager.getInstance();
|
WalletManager mgr = WalletManager.getInstance();
|
||||||
List<WalletManager.WalletInfo> walletInfos =
|
List<WalletManager.WalletInfo> walletInfos =
|
||||||
mgr.findWallets(activityCallback.getStorageRoot());
|
mgr.findWallets(activityCallback.getStorageRoot());
|
||||||
@@ -315,7 +315,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean onTestnetMenuItem() {
|
public boolean onTestnetMenuItem() {
|
||||||
boolean lastState = testnet;//item.isChecked();
|
boolean lastState = testnet;
|
||||||
setNet(!lastState, true); // set and save
|
setNet(!lastState, true); // set and save
|
||||||
return !lastState;
|
return !lastState;
|
||||||
}
|
}
|
||||||
@@ -336,7 +336,6 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
|
|
||||||
private static final String PREF_DAEMON_TESTNET = "daemon_testnet";
|
private static final String PREF_DAEMON_TESTNET = "daemon_testnet";
|
||||||
private static final String PREF_DAEMON_MAINNET = "daemon_mainnet";
|
private static final String PREF_DAEMON_MAINNET = "daemon_mainnet";
|
||||||
//private static final String PREF_TESTNET = "testnet";
|
|
||||||
|
|
||||||
private static final String PREF_DAEMONLIST_MAINNET =
|
private static final String PREF_DAEMONLIST_MAINNET =
|
||||||
"node.moneroworld.com:18089;node.xmrbackb.one;node.xmr.be";
|
"node.moneroworld.com:18089;node.xmrbackb.one;node.xmr.be";
|
||||||
@@ -360,7 +359,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
void savePrefs(boolean usePreviousState) {
|
void savePrefs(boolean usePreviousState) {
|
||||||
Log.d(TAG, "SAVE / " + usePreviousState);
|
Timber.d("SAVE / %s", usePreviousState);
|
||||||
// save the daemon address for the net
|
// save the daemon address for the net
|
||||||
boolean testnet = isTestnet() ^ usePreviousState;
|
boolean testnet = isTestnet() ^ usePreviousState;
|
||||||
String daemon = getDaemon();
|
String daemon = getDaemon();
|
||||||
@@ -372,7 +371,6 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
|
|
||||||
SharedPreferences sharedPref = activityCallback.getPrefs();
|
SharedPreferences sharedPref = activityCallback.getPrefs();
|
||||||
SharedPreferences.Editor editor = sharedPref.edit();
|
SharedPreferences.Editor editor = sharedPref.edit();
|
||||||
//editor.putBoolean(PREF_TESTNET, testnet);
|
|
||||||
editor.putString(PREF_DAEMON_MAINNET, daemonMainNet.toString());
|
editor.putString(PREF_DAEMON_MAINNET, daemonMainNet.toString());
|
||||||
editor.putString(PREF_DAEMON_TESTNET, daemonTestNet.toString());
|
editor.putString(PREF_DAEMON_TESTNET, daemonTestNet.toString());
|
||||||
editor.apply();
|
editor.apply();
|
||||||
@@ -383,7 +381,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setDaemon(NodeList nodeList) {
|
void setDaemon(NodeList nodeList) {
|
||||||
Log.d(TAG, "setDaemon() " + nodeList.toString());
|
Timber.d("setDaemon() %s", nodeList.toString());
|
||||||
String[] nodes = nodeList.getNodes().toArray(new String[0]);
|
String[] nodes = nodeList.getNodes().toArray(new String[0]);
|
||||||
nodeAdapter.clear();
|
nodeAdapter.clear();
|
||||||
nodeAdapter.addAll(nodes);
|
nodeAdapter.addAll(nodes);
|
||||||
|
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public interface OnBackPressedListener {
|
||||||
|
boolean onBackPressed();
|
||||||
|
}
|
@@ -19,6 +19,7 @@ package com.m2049r.xmrwallet;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.design.widget.TextInputLayout;
|
import android.support.design.widget.TextInputLayout;
|
||||||
@@ -26,7 +27,6 @@ import android.support.v4.app.Fragment;
|
|||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -46,31 +46,31 @@ import com.google.zxing.WriterException;
|
|||||||
import com.google.zxing.common.BitMatrix;
|
import com.google.zxing.common.BitMatrix;
|
||||||
import com.google.zxing.qrcode.QRCodeWriter;
|
import com.google.zxing.qrcode.QRCodeWriter;
|
||||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||||
import com.m2049r.xmrwallet.layout.ExchangeView;
|
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||||
|
import com.m2049r.xmrwallet.widget.ExchangeView;
|
||||||
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class ReceiveFragment extends Fragment {
|
public class ReceiveFragment extends Fragment {
|
||||||
static final String TAG = "ReceiveFragment";
|
|
||||||
|
|
||||||
private ProgressBar pbProgress;
|
private ProgressBar pbProgress;
|
||||||
private TextView tvAddress;
|
private TextView tvAddress;
|
||||||
private TextInputLayout etPaymentId;
|
private TextInputLayout etPaymentId;
|
||||||
private ExchangeView evAmount;
|
private ExchangeView evAmount;
|
||||||
private Button bPaymentId;
|
private Button bPaymentId;
|
||||||
private Button bGenerate;
|
private TextView tvQrCode;
|
||||||
private ImageView qrCode;
|
private ImageView qrCode;
|
||||||
|
private ImageView qrCodeFull;
|
||||||
private EditText etDummy;
|
private EditText etDummy;
|
||||||
private ImageButton bCopyAddress;
|
private ImageButton bCopyAddress;
|
||||||
|
|
||||||
//String name;
|
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
void setToolbarButton(int type);
|
void setToolbarButton(int type);
|
||||||
|
|
||||||
@@ -91,7 +91,8 @@ public class ReceiveFragment extends Fragment {
|
|||||||
evAmount = (ExchangeView) view.findViewById(R.id.evAmount);
|
evAmount = (ExchangeView) view.findViewById(R.id.evAmount);
|
||||||
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
|
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
|
||||||
qrCode = (ImageView) view.findViewById(R.id.qrCode);
|
qrCode = (ImageView) view.findViewById(R.id.qrCode);
|
||||||
bGenerate = (Button) view.findViewById(R.id.bGenerate);
|
tvQrCode = (TextView) view.findViewById(R.id.tvQrCode);
|
||||||
|
qrCodeFull = (ImageView) view.findViewById(R.id.qrCodeFull);
|
||||||
etDummy = (EditText) view.findViewById(R.id.etDummy);
|
etDummy = (EditText) view.findViewById(R.id.etDummy);
|
||||||
bCopyAddress = (ImageButton) view.findViewById(R.id.bCopyAddress);
|
bCopyAddress = (ImageButton) view.findViewById(R.id.bCopyAddress);
|
||||||
|
|
||||||
@@ -108,7 +109,7 @@ public class ReceiveFragment extends Fragment {
|
|||||||
evAmount.setOnNewAmountListener(new ExchangeView.OnNewAmountListener() {
|
evAmount.setOnNewAmountListener(new ExchangeView.OnNewAmountListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onNewAmount(String xmr) {
|
public void onNewAmount(String xmr) {
|
||||||
Log.d(TAG, "new amount = " + xmr);
|
Timber.d("new amount = %s", xmr);
|
||||||
generateQr();
|
generateQr();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -116,9 +117,11 @@ public class ReceiveFragment extends Fragment {
|
|||||||
evAmount.setOnFailedExchangeListener(new ExchangeView.OnFailedExchangeListener() {
|
evAmount.setOnFailedExchangeListener(new ExchangeView.OnFailedExchangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onFailedExchange() {
|
public void onFailedExchange() {
|
||||||
|
if (isAdded()) {
|
||||||
clearQR();
|
clearQR();
|
||||||
Toast.makeText(getActivity(), getString(R.string.message_exchange_failed), Toast.LENGTH_LONG).show();
|
Toast.makeText(getActivity(), getString(R.string.message_exchange_failed), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
etPaymentId.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
etPaymentId.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||||
@@ -146,7 +149,6 @@ public class ReceiveFragment extends Fragment {
|
|||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
bPaymentId.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@@ -158,22 +160,33 @@ public class ReceiveFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bGenerate.setOnClickListener(new View.OnClickListener() {
|
qrCode.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (checkPaymentId()) {
|
if (qrValid) {
|
||||||
|
qrCodeFull.setImageBitmap(((BitmapDrawable) qrCode.getDrawable()).getBitmap());
|
||||||
|
qrCodeFull.setVisibility(View.VISIBLE);
|
||||||
|
} else if (checkPaymentId()) {
|
||||||
evAmount.doExchange();
|
evAmount.doExchange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
qrCodeFull.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
qrCodeFull.setImageBitmap(null);
|
||||||
|
qrCodeFull.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
showProgress();
|
showProgress();
|
||||||
clearQR();
|
clearQR();
|
||||||
|
|
||||||
Bundle b = getArguments();
|
Bundle b = getArguments();
|
||||||
String address = b.getString("address");
|
String address = b.getString("address");
|
||||||
String walletName = b.getString("name");
|
String walletName = b.getString("name");
|
||||||
Log.d(TAG, "address=" + address + "/name=" + walletName);
|
Timber.d("%s/%s", address, walletName);
|
||||||
if (address == null) {
|
if (address == null) {
|
||||||
String path = b.getString("path");
|
String path = b.getString("path");
|
||||||
String password = b.getString("password");
|
String password = b.getString("password");
|
||||||
@@ -193,14 +206,17 @@ public class ReceiveFragment extends Fragment {
|
|||||||
|
|
||||||
void clearQR() {
|
void clearQR() {
|
||||||
if (qrValid) {
|
if (qrValid) {
|
||||||
qrCode.setImageBitmap(getMoneroLogo());
|
qrCode.setImageBitmap(null);
|
||||||
qrValid = false;
|
qrValid = false;
|
||||||
|
if (isLoaded)
|
||||||
|
tvQrCode.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setQR(Bitmap qr) {
|
void setQR(Bitmap qr) {
|
||||||
qrCode.setImageBitmap(qr);
|
qrCode.setImageBitmap(qr);
|
||||||
qrValid = true;
|
qrValid = true;
|
||||||
|
tvQrCode.setVisibility(View.INVISIBLE);
|
||||||
Helper.hideKeyboard(getActivity());
|
Helper.hideKeyboard(getActivity());
|
||||||
etDummy.requestFocus();
|
etDummy.requestFocus();
|
||||||
}
|
}
|
||||||
@@ -208,20 +224,21 @@ public class ReceiveFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Timber.d("onResume()");
|
||||||
listenerCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
listenerCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
||||||
listenerCallback.setSubtitle(getString(R.string.receive_title));
|
listenerCallback.setSubtitle(getString(R.string.receive_title));
|
||||||
generateQr();
|
generateQr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isLoaded = false;
|
||||||
|
|
||||||
private void show(String name, String address) {
|
private void show(String name, String address) {
|
||||||
Log.d(TAG, "name=" + name);
|
Timber.d("name=%s", name);
|
||||||
|
isLoaded = true;
|
||||||
listenerCallback.setTitle(name);
|
listenerCallback.setTitle(name);
|
||||||
tvAddress.setText(address);
|
tvAddress.setText(address);
|
||||||
etPaymentId.setEnabled(true);
|
etPaymentId.setEnabled(true);
|
||||||
//etAmount.setEnabled(true);
|
|
||||||
bPaymentId.setEnabled(true);
|
bPaymentId.setEnabled(true);
|
||||||
bGenerate.setEnabled(true);
|
|
||||||
bCopyAddress.setEnabled(true);
|
bCopyAddress.setEnabled(true);
|
||||||
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
|
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
|
||||||
hideProgress();
|
hideProgress();
|
||||||
@@ -276,14 +293,14 @@ public class ReceiveFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateQr() {
|
private void generateQr() {
|
||||||
Log.d(TAG, "GENQR");
|
Timber.d("GENQR");
|
||||||
String address = tvAddress.getText().toString();
|
String address = tvAddress.getText().toString();
|
||||||
String paymentId = etPaymentId.getEditText().getText().toString();
|
String paymentId = etPaymentId.getEditText().getText().toString();
|
||||||
String xmrAmount = evAmount.getAmount();
|
String xmrAmount = evAmount.getAmount();
|
||||||
Log.d(TAG, xmrAmount + "/" + paymentId + "/" + address);
|
Timber.d("%s/%s/%s", xmrAmount, paymentId, address);
|
||||||
if ((xmrAmount == null) || !Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet())) {
|
if ((xmrAmount == null) || !Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet())) {
|
||||||
clearQR();
|
clearQR();
|
||||||
Log.d(TAG, "CLEARQR");
|
Timber.d("CLEARQR");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
@@ -305,10 +322,11 @@ public class ReceiveFragment extends Fragment {
|
|||||||
sb.append(ScannerFragment.QR_AMOUNT).append('=').append(xmrAmount);
|
sb.append(ScannerFragment.QR_AMOUNT).append('=').append(xmrAmount);
|
||||||
}
|
}
|
||||||
String text = sb.toString();
|
String text = sb.toString();
|
||||||
Bitmap qr = generate(text, 500, 500);
|
int size = Math.min(qrCode.getHeight(), qrCode.getWidth());
|
||||||
|
Bitmap qr = generate(text, size, size);
|
||||||
if (qr != null) {
|
if (qr != null) {
|
||||||
setQR(qr);
|
setQR(qr);
|
||||||
Log.d(TAG, "SETQR");
|
Timber.d("SETQR");
|
||||||
etDummy.requestFocus();
|
etDummy.requestFocus();
|
||||||
Helper.hideKeyboard(getActivity());
|
Helper.hideKeyboard(getActivity());
|
||||||
}
|
}
|
||||||
@@ -339,7 +357,6 @@ public class ReceiveFragment extends Fragment {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO check if we can sensibly cache some of this
|
|
||||||
private Bitmap addLogo(Bitmap qrBitmap) {
|
private Bitmap addLogo(Bitmap qrBitmap) {
|
||||||
Bitmap logo = getMoneroLogo();
|
Bitmap logo = getMoneroLogo();
|
||||||
int qrWidth = qrBitmap.getWidth();
|
int qrWidth = qrBitmap.getWidth();
|
||||||
@@ -393,12 +410,9 @@ public class ReceiveFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String PREF_CURRENCY_A = "PREF_CURRENCY_A";
|
|
||||||
static final String PREF_CURRENCY_B = "PREF_CURRENCY_B";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
Log.d(TAG, "onPause()");
|
Timber.d("onPause()");
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,6 @@ import android.content.Context;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -30,21 +29,21 @@ import com.google.zxing.BarcodeFormat;
|
|||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
|
||||||
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
|
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
|
||||||
static final String TAG = "ScannerFragment";
|
|
||||||
|
|
||||||
private Listener activityCallback;
|
private OnScannedListener onScannedListener;
|
||||||
|
|
||||||
public interface Listener {
|
public interface OnScannedListener {
|
||||||
boolean onAddressScanned(String uri);
|
boolean onScanned(String uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ZXingScannerView mScannerView;
|
private ZXingScannerView mScannerView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
Log.d(TAG, "onCreateView");
|
Timber.d("onCreateView");
|
||||||
mScannerView = new ZXingScannerView(getActivity());
|
mScannerView = new ZXingScannerView(getActivity());
|
||||||
return mScannerView;
|
return mScannerView;
|
||||||
}
|
}
|
||||||
@@ -52,7 +51,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume");
|
Timber.d("onResume");
|
||||||
mScannerView.setResultHandler(this);
|
mScannerView.setResultHandler(this);
|
||||||
mScannerView.startCamera();
|
mScannerView.startCamera();
|
||||||
}
|
}
|
||||||
@@ -63,9 +62,8 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleResult(Result rawResult) {
|
public void handleResult(Result rawResult) {
|
||||||
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
|
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE)) {
|
||||||
(rawResult.getText().startsWith(QR_SCHEME))) {
|
if (onScannedListener.onScanned(rawResult.getText())) {
|
||||||
if (activityCallback.onAddressScanned(rawResult.getText())) {
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), getString(R.string.send_qr_address_invalid), Toast.LENGTH_SHORT).show();
|
||||||
@@ -91,7 +89,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
Log.d(TAG, "onPause");
|
Timber.d("onPause");
|
||||||
mScannerView.stopCamera();
|
mScannerView.stopCamera();
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
@@ -99,8 +97,8 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
|||||||
@Override
|
@Override
|
||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
if (context instanceof Listener) {
|
if (context instanceof OnScannedListener) {
|
||||||
this.activityCallback = (Listener) context;
|
this.onScannedListener = (OnScannedListener) context;
|
||||||
} else {
|
} else {
|
||||||
throw new ClassCastException(context.toString()
|
throw new ClassCastException(context.toString()
|
||||||
+ " must implement Listener");
|
+ " must implement Listener");
|
||||||
|
35
app/src/main/java/com/m2049r/xmrwallet/SecureActivity.java
Normal file
35
app/src/main/java/com/m2049r/xmrwallet/SecureActivity.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import static android.view.WindowManager.LayoutParams;
|
||||||
|
|
||||||
|
public abstract class SecureActivity extends AppCompatActivity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// set FLAG_SECURE to prevent screenshots in Release Mode
|
||||||
|
if (!BuildConfig.DEBUG) {
|
||||||
|
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.data.BarcodeData;
|
||||||
|
import com.m2049r.xmrwallet.widget.ExchangeTextView;
|
||||||
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
import com.m2049r.xmrwallet.widget.NumberPadView;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class SendAmountWizardFragment extends SendWizardFragment {
|
||||||
|
|
||||||
|
public static SendAmountWizardFragment newInstance(Listener listener) {
|
||||||
|
SendAmountWizardFragment instance = new SendAmountWizardFragment();
|
||||||
|
instance.setSendListener(listener);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Listener sendListener;
|
||||||
|
|
||||||
|
public SendAmountWizardFragment setSendListener(Listener listener) {
|
||||||
|
this.sendListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Listener {
|
||||||
|
SendFragment.Listener getActivityCallback();
|
||||||
|
|
||||||
|
void setAmount(final long amount);
|
||||||
|
|
||||||
|
BarcodeData popBarcodeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextView tvFunds;
|
||||||
|
private ExchangeTextView evAmount;
|
||||||
|
//private Button bSendAll;
|
||||||
|
private NumberPadView numberPad;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
Timber.d("onCreateView() %s", (String.valueOf(savedInstanceState)));
|
||||||
|
|
||||||
|
sendListener = (Listener) getParentFragment();
|
||||||
|
|
||||||
|
View view = inflater.inflate(R.layout.fragment_send_amount, container, false);
|
||||||
|
|
||||||
|
tvFunds = (TextView) view.findViewById(R.id.tvFunds);
|
||||||
|
|
||||||
|
evAmount = (ExchangeTextView) view.findViewById(R.id.evAmount);
|
||||||
|
numberPad = (NumberPadView) view.findViewById(R.id.numberPad);
|
||||||
|
numberPad.setListener(evAmount);
|
||||||
|
|
||||||
|
/*
|
||||||
|
bSendAll = (Button) view.findViewById(R.id.bSendAll);
|
||||||
|
bSendAll.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
// TODO: send all - figure out how to display this
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
Helper.hideKeyboard(getActivity());
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onValidateFields() {
|
||||||
|
if (!evAmount.validate(maxFunds)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendListener != null) {
|
||||||
|
String xmr = evAmount.getAmount();
|
||||||
|
if (xmr != null) {
|
||||||
|
sendListener.setAmount(Wallet.getAmountFromString(xmr));
|
||||||
|
} else {
|
||||||
|
sendListener.setAmount(0L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
double maxFunds = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResumeFragment() {
|
||||||
|
super.onResumeFragment();
|
||||||
|
Timber.d("onResumeFragment()");
|
||||||
|
Helper.hideKeyboard(getActivity());
|
||||||
|
final long funds = getTotalFunds();
|
||||||
|
maxFunds = 1.0 * funds / 1000000000000L;
|
||||||
|
tvFunds.setText(getString(R.string.send_available,
|
||||||
|
Wallet.getDisplayAmount(funds)));
|
||||||
|
// getAmount is null if exchange is in progress
|
||||||
|
if ((evAmount.getAmount() != null) && evAmount.getAmount().isEmpty()) {
|
||||||
|
final BarcodeData data = sendListener.popBarcodeData();
|
||||||
|
if ((data != null) && (data.amount != null)) {
|
||||||
|
evAmount.setAmount(data.amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long getTotalFunds() {
|
||||||
|
return sendListener.getActivityCallback().getTotalFunds();
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.InputType;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class SendSettingsWizardFragment extends SendWizardFragment {
|
||||||
|
|
||||||
|
public static SendSettingsWizardFragment newInstance(Listener listener) {
|
||||||
|
SendSettingsWizardFragment instance = new SendSettingsWizardFragment();
|
||||||
|
instance.setSendListener(listener);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Listener sendListener;
|
||||||
|
|
||||||
|
public SendSettingsWizardFragment setSendListener(Listener listener) {
|
||||||
|
this.sendListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Listener {
|
||||||
|
|
||||||
|
void setPriority(final PendingTransaction.Priority priority);
|
||||||
|
|
||||||
|
void setMixin(final int mixin);
|
||||||
|
|
||||||
|
void setNotes(final String notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
final static int Mixins[] = {4, 7, 12, 25}; // must match the layout XML
|
||||||
|
final static PendingTransaction.Priority Priorities[] =
|
||||||
|
{PendingTransaction.Priority.Priority_Default,
|
||||||
|
PendingTransaction.Priority.Priority_Low,
|
||||||
|
PendingTransaction.Priority.Priority_Medium,
|
||||||
|
PendingTransaction.Priority.Priority_High}; // must match the layout XML
|
||||||
|
|
||||||
|
private Spinner sMixin;
|
||||||
|
private Spinner sPriority;
|
||||||
|
private EditText etNotes;
|
||||||
|
private EditText etDummy;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
Timber.d("onCreateView() %s", (String.valueOf(savedInstanceState)));
|
||||||
|
|
||||||
|
View view = inflater.inflate(
|
||||||
|
R.layout.fragment_send_settings, container, false);
|
||||||
|
|
||||||
|
sMixin = (Spinner) view.findViewById(R.id.sMixin);
|
||||||
|
sPriority = (Spinner) view.findViewById(R.id.sPriority);
|
||||||
|
|
||||||
|
etNotes = (EditText) view.findViewById(R.id.etNotes);
|
||||||
|
etNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||||
|
etNotes.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)) {
|
||||||
|
etDummy.requestFocus();
|
||||||
|
Helper.hideKeyboard(getActivity());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
etDummy = (EditText) view.findViewById(R.id.etDummy);
|
||||||
|
etDummy.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onValidateFields() {
|
||||||
|
if (sendListener != null) {
|
||||||
|
int mixin = Mixins[sMixin.getSelectedItemPosition()];
|
||||||
|
int priorityIndex = sPriority.getSelectedItemPosition();
|
||||||
|
PendingTransaction.Priority priority = Priorities[priorityIndex];
|
||||||
|
sendListener.setPriority(priority);
|
||||||
|
sendListener.setMixin(mixin);
|
||||||
|
String notes = etNotes.getText().toString();
|
||||||
|
sendListener.setNotes(notes);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResumeFragment() {
|
||||||
|
super.onResumeFragment();
|
||||||
|
Timber.d("onResumeFragment()");
|
||||||
|
Helper.hideKeyboard(getActivity());
|
||||||
|
etDummy.requestFocus();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
import com.m2049r.xmrwallet.data.PendingTx;
|
||||||
|
import com.m2049r.xmrwallet.data.TxData;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class SendSuccessWizardFragment extends SendWizardFragment {
|
||||||
|
|
||||||
|
public static SendSuccessWizardFragment newInstance(Listener listener) {
|
||||||
|
SendSuccessWizardFragment instance = new SendSuccessWizardFragment();
|
||||||
|
instance.setSendListener(listener);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Listener sendListener;
|
||||||
|
|
||||||
|
public SendSuccessWizardFragment setSendListener(Listener listener) {
|
||||||
|
this.sendListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Listener {
|
||||||
|
String getNotes();
|
||||||
|
|
||||||
|
TxData getTxData();
|
||||||
|
|
||||||
|
PendingTx getCommittedTx();
|
||||||
|
|
||||||
|
void enableDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageButton bCopyAddress;
|
||||||
|
private TextView tvTxId;
|
||||||
|
private TextView tvTxAddress;
|
||||||
|
private TextView tvTxPaymentId;
|
||||||
|
private TextView tvTxNotes;
|
||||||
|
private TextView tvTxAmount;
|
||||||
|
private TextView tvTxFee;
|
||||||
|
private TextView tvTxTotal;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
Timber.d("onCreateView() %s", (String.valueOf(savedInstanceState)));
|
||||||
|
|
||||||
|
View view = inflater.inflate(
|
||||||
|
R.layout.fragment_send_success, container, false);
|
||||||
|
|
||||||
|
bCopyAddress = (ImageButton) view.findViewById(R.id.bCopyAddress);
|
||||||
|
bCopyAddress.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
copyAddress();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tvTxId = (TextView) view.findViewById(R.id.tvTxId);
|
||||||
|
tvTxAddress = (TextView) view.findViewById(R.id.tvTxAddress);
|
||||||
|
tvTxPaymentId = (TextView) view.findViewById(R.id.tvTxPaymentId);
|
||||||
|
tvTxNotes = (TextView) view.findViewById(R.id.tvTxNotes);
|
||||||
|
tvTxAmount = ((TextView) view.findViewById(R.id.tvTxAmount));
|
||||||
|
tvTxFee = (TextView) view.findViewById(R.id.tvTxFee);
|
||||||
|
tvTxTotal = (TextView) view.findViewById(R.id.tvTxTotal);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onValidateFields() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPauseFragment() {
|
||||||
|
super.onPauseFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResumeFragment() {
|
||||||
|
super.onResumeFragment();
|
||||||
|
Timber.d("onResumeFragment()");
|
||||||
|
Helper.hideKeyboard(getActivity());
|
||||||
|
|
||||||
|
final TxData txData = sendListener.getTxData();
|
||||||
|
tvTxAddress.setText(txData.getDestinationAddress());
|
||||||
|
String paymentId = txData.getPaymentId();
|
||||||
|
if ((paymentId != null) && (!paymentId.isEmpty())) {
|
||||||
|
tvTxPaymentId.setText(txData.getPaymentId());
|
||||||
|
} else {
|
||||||
|
tvTxPaymentId.setText("-");
|
||||||
|
}
|
||||||
|
String notes = sendListener.getNotes();
|
||||||
|
if ((notes != null) && (!notes.isEmpty())) {
|
||||||
|
tvTxNotes.setText(sendListener.getNotes());
|
||||||
|
} else {
|
||||||
|
tvTxNotes.setText("-");
|
||||||
|
}
|
||||||
|
|
||||||
|
final PendingTx committedTx = sendListener.getCommittedTx();
|
||||||
|
if (committedTx != null) {
|
||||||
|
tvTxId.setText(committedTx.txId);
|
||||||
|
bCopyAddress.setEnabled(true);
|
||||||
|
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
|
||||||
|
tvTxAmount.setText(Wallet.getDisplayAmount(committedTx.amount));
|
||||||
|
tvTxFee.setText(Wallet.getDisplayAmount(committedTx.fee));
|
||||||
|
//tvTxDust.setText(Wallet.getDisplayAmount(pendingTransaction.getDust()));
|
||||||
|
tvTxTotal.setText(Wallet.getDisplayAmount(
|
||||||
|
committedTx.fee + committedTx.amount));
|
||||||
|
}
|
||||||
|
sendListener.enableDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyAddress() {
|
||||||
|
Helper.clipBoardCopy(getActivity(), getString(R.string.label_send_txid), tvTxId.getText().toString());
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.layout.SpendViewPager;
|
||||||
|
|
||||||
|
abstract public class SendWizardFragment extends Fragment
|
||||||
|
implements SpendViewPager.OnValidateFieldsListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onValidateFields() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPauseFragment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResumeFragment() {
|
||||||
|
}
|
||||||
|
}
|
@@ -31,10 +31,10 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.layout.Toolbar;
|
|
||||||
import com.m2049r.xmrwallet.model.TransactionInfo;
|
import com.m2049r.xmrwallet.model.TransactionInfo;
|
||||||
import com.m2049r.xmrwallet.model.Transfer;
|
import com.m2049r.xmrwallet.model.Transfer;
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
import com.m2049r.xmrwallet.widget.Toolbar;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@@ -44,7 +44,6 @@ import java.util.Set;
|
|||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
public class TxFragment extends Fragment {
|
public class TxFragment extends Fragment {
|
||||||
static final String TAG = "TxFragment";
|
|
||||||
|
|
||||||
static public final String ARG_INFO = "info";
|
static public final String ARG_INFO = "info";
|
||||||
|
|
||||||
@@ -167,8 +166,7 @@ public class TxFragment extends Fragment {
|
|||||||
sb.append("-");
|
sb.append("-");
|
||||||
}
|
}
|
||||||
sb.append("\n\n");
|
sb.append("\n\n");
|
||||||
//Helper.clipBoardCopy(getActivity(), getString(R.string.tx_copy_label), sb.toString());
|
|
||||||
//Toast.makeText(getActivity(), getString(R.string.tx_copy_message), Toast.LENGTH_SHORT).show();
|
|
||||||
Intent sendIntent = new Intent();
|
Intent sendIntent = new Intent();
|
||||||
sendIntent.setAction(Intent.ACTION_SEND);
|
sendIntent.setAction(Intent.ACTION_SEND);
|
||||||
sendIntent.putExtra(Intent.EXTRA_TEXT, sb.toString());
|
sendIntent.putExtra(Intent.EXTRA_TEXT, sb.toString());
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 m2049r et al.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class XmrWalletApplication extends Application {
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Timber.plant(new Timber.DebugTree());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java
Normal file
137
app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class BarcodeData {
|
||||||
|
public static final String XMR_SCHEME = "monero:";
|
||||||
|
public static final String XMR_PAYMENTID = "tx_payment_id";
|
||||||
|
public static final String XMR_AMOUNT = "tx_amount";
|
||||||
|
|
||||||
|
static final String BTC_SCHEME = "bitcoin:";
|
||||||
|
static final String BTC_AMOUNT = "amount";
|
||||||
|
|
||||||
|
public enum Asset {
|
||||||
|
XMR
|
||||||
|
}
|
||||||
|
|
||||||
|
public Asset asset = null;
|
||||||
|
public String address = null;
|
||||||
|
public String paymentId = null;
|
||||||
|
public String amount = null;
|
||||||
|
|
||||||
|
public BarcodeData(Asset asset, String address) {
|
||||||
|
this.asset = asset;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BarcodeData(Asset asset, String address, String amount) {
|
||||||
|
this.asset = asset;
|
||||||
|
this.address = address;
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BarcodeData(Asset asset, String address, String paymentId, String amount) {
|
||||||
|
this.asset = asset;
|
||||||
|
this.address = address;
|
||||||
|
this.paymentId = paymentId;
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public BarcodeData fromQrCode(String qrCode) {
|
||||||
|
// check for monero uri
|
||||||
|
BarcodeData bcData = parseMoneroUri(qrCode);
|
||||||
|
// check for naked monero address / integrated address
|
||||||
|
if (bcData == null) {
|
||||||
|
bcData = parseMoneroNaked(qrCode);
|
||||||
|
}
|
||||||
|
return bcData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse and decode a monero scheme string. It is here because it needs to validate the data.
|
||||||
|
*
|
||||||
|
* @param uri String containing a monero URL
|
||||||
|
* @return BarcodeData object or null if uri not valid
|
||||||
|
*/
|
||||||
|
|
||||||
|
static public BarcodeData parseMoneroUri(String uri) {
|
||||||
|
Timber.d("parseMoneroUri=%s", uri);
|
||||||
|
|
||||||
|
if (uri == null) return null;
|
||||||
|
|
||||||
|
if (!uri.startsWith(XMR_SCHEME)) return null;
|
||||||
|
|
||||||
|
String noScheme = uri.substring(XMR_SCHEME.length());
|
||||||
|
Uri monero = Uri.parse(noScheme);
|
||||||
|
Map<String, String> parms = new HashMap<>();
|
||||||
|
String query = monero.getQuery();
|
||||||
|
if (query != null) {
|
||||||
|
String[] args = query.split("&");
|
||||||
|
for (String arg : args) {
|
||||||
|
String[] namevalue = arg.split("=");
|
||||||
|
if (namevalue.length == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parms.put(Uri.decode(namevalue[0]).toLowerCase(),
|
||||||
|
namevalue.length > 1 ? Uri.decode(namevalue[1]) : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String address = monero.getPath();
|
||||||
|
String paymentId = parms.get(XMR_PAYMENTID);
|
||||||
|
String amount = parms.get(XMR_AMOUNT);
|
||||||
|
if (amount != null) {
|
||||||
|
try {
|
||||||
|
Double.parseDouble(amount);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
Timber.d(ex.getLocalizedMessage());
|
||||||
|
return null; // we have an amount but its not a number!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((paymentId != null) && !Wallet.isPaymentIdValid(paymentId)) {
|
||||||
|
Timber.d("paymentId invalid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Wallet.isAddressValid(address)) {
|
||||||
|
Timber.d("address invalid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new BarcodeData(Asset.XMR, address, paymentId, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public BarcodeData parseMoneroNaked(String address) {
|
||||||
|
Timber.d("parseMoneroNaked=%s", address);
|
||||||
|
|
||||||
|
if (address == null) return null;
|
||||||
|
|
||||||
|
if (!Wallet.isAddressValid(address)) {
|
||||||
|
Timber.d("address invalid");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BarcodeData(Asset.XMR, address);
|
||||||
|
}
|
||||||
|
}
|
39
app/src/main/java/com/m2049r/xmrwallet/data/PendingTx.java
Normal file
39
app/src/main/java/com/m2049r/xmrwallet/data/PendingTx.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||||
|
|
||||||
|
public class PendingTx {
|
||||||
|
final public PendingTransaction.Status status;
|
||||||
|
final public String error;
|
||||||
|
final public long amount;
|
||||||
|
final public long dust;
|
||||||
|
final public long fee;
|
||||||
|
final public String txId;
|
||||||
|
final public long txCount;
|
||||||
|
|
||||||
|
public PendingTx(PendingTransaction pendingTransaction) {
|
||||||
|
status = pendingTransaction.getStatus();
|
||||||
|
error = pendingTransaction.getErrorString();
|
||||||
|
amount = pendingTransaction.getAmount();
|
||||||
|
dust = pendingTransaction.getDust();
|
||||||
|
fee = pendingTransaction.getFee();
|
||||||
|
txId = pendingTransaction.getFirstTxId();
|
||||||
|
txCount = pendingTransaction.getTxCount();
|
||||||
|
}
|
||||||
|
}
|
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.m2049r.xmrwallet.util;
|
package com.m2049r.xmrwallet.data;
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
@@ -23,6 +23,15 @@ import com.m2049r.xmrwallet.model.PendingTransaction;
|
|||||||
|
|
||||||
// https://stackoverflow.com/questions/2139134/how-to-send-an-object-from-one-android-activity-to-another-using-intents
|
// https://stackoverflow.com/questions/2139134/how-to-send-an-object-from-one-android-activity-to-another-using-intents
|
||||||
public class TxData implements Parcelable {
|
public class TxData implements Parcelable {
|
||||||
|
|
||||||
|
public TxData(TxData txData) {
|
||||||
|
this.dst_addr = txData.dst_addr;
|
||||||
|
this.paymentId = txData.paymentId;
|
||||||
|
this.amount = txData.amount;
|
||||||
|
this.mixin = txData.mixin;
|
||||||
|
this.priority = txData.priority;
|
||||||
|
}
|
||||||
|
|
||||||
public TxData(String dst_addr,
|
public TxData(String dst_addr,
|
||||||
String paymentId,
|
String paymentId,
|
||||||
long amount,
|
long amount,
|
||||||
@@ -35,11 +44,35 @@ public class TxData implements Parcelable {
|
|||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String dst_addr;
|
public long getFee() {
|
||||||
public String paymentId;
|
return 0L;
|
||||||
public long amount;
|
}
|
||||||
public int mixin;
|
|
||||||
public PendingTransaction.Priority priority;
|
public String getDestinationAddress() {
|
||||||
|
return dst_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPaymentId() {
|
||||||
|
return paymentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMixin() {
|
||||||
|
return mixin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PendingTransaction.Priority getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
final private String dst_addr;
|
||||||
|
final private String paymentId;
|
||||||
|
final private long amount;
|
||||||
|
final private int mixin;
|
||||||
|
final private PendingTransaction.Priority priority;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel out, int flags) {
|
public void writeToParcel(Parcel out, int flags) {
|
||||||
@@ -87,7 +120,7 @@ public class TxData implements Parcelable {
|
|||||||
sb.append(",mixin:");
|
sb.append(",mixin:");
|
||||||
sb.append(mixin);
|
sb.append(mixin);
|
||||||
sb.append(",priority:");
|
sb.append(",priority:");
|
||||||
sb.append(priority.toString());
|
sb.append(String.valueOf(priority));
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,159 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.layout;
|
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
public class AsyncExchangeRate extends AsyncTask<String, Void, Boolean> {
|
|
||||||
static final String TAG = "AsyncExchangeRate";
|
|
||||||
static final long TIME_REFRESH_INTERVAL = 60000; // refresh exchange rate max every minute
|
|
||||||
|
|
||||||
public interface Listener {
|
|
||||||
void exchangeFailed();
|
|
||||||
|
|
||||||
// callback from AsyncExchangeRate when we have a rate
|
|
||||||
void exchange(String currencyA, String currencyB, double rate);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long RateTime = 0;
|
|
||||||
static double Rate = 0;
|
|
||||||
static String Fiat = null;
|
|
||||||
|
|
||||||
private final WeakReference<Listener> exchangeViewRef;
|
|
||||||
|
|
||||||
public AsyncExchangeRate(Listener exchangeView) {
|
|
||||||
super();
|
|
||||||
exchangeViewRef = new WeakReference<>(exchangeView);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
super.onPreExecute();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean inverse = false;
|
|
||||||
String currencyA = null;
|
|
||||||
String currencyB = null;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(String... params) {
|
|
||||||
if (params.length != 2) return false;
|
|
||||||
Log.d(TAG, "Getting " + params[0]);
|
|
||||||
currencyA = params[0];
|
|
||||||
currencyB = params[1];
|
|
||||||
|
|
||||||
String fiat = null;
|
|
||||||
if (currencyA.equals("XMR")) {
|
|
||||||
fiat = currencyB;
|
|
||||||
inverse = false;
|
|
||||||
}
|
|
||||||
if (currencyB.equals("XMR")) {
|
|
||||||
fiat = currencyA;
|
|
||||||
inverse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currencyA.equals(currencyB)) {
|
|
||||||
Fiat = null;
|
|
||||||
Rate = 1;
|
|
||||||
RateTime = System.currentTimeMillis();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fiat == null) {
|
|
||||||
Fiat = null;
|
|
||||||
Rate = 0;
|
|
||||||
RateTime = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fiat.equals(Fiat)) { // new currency - reset all
|
|
||||||
Fiat = fiat;
|
|
||||||
Rate = 0;
|
|
||||||
RateTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (System.currentTimeMillis() > RateTime + TIME_REFRESH_INTERVAL) {
|
|
||||||
Log.d(TAG, "Fetching " + Fiat);
|
|
||||||
String closePrice = getExchangeRate(Fiat);
|
|
||||||
if (closePrice != null) {
|
|
||||||
try {
|
|
||||||
Rate = Double.parseDouble(closePrice);
|
|
||||||
RateTime = System.currentTimeMillis();
|
|
||||||
return true;
|
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
Rate = 0;
|
|
||||||
Log.e(TAG, ex.getLocalizedMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Rate = 0;
|
|
||||||
Log.e(TAG, "exchange url failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; // no change but still valid
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean result) {
|
|
||||||
super.onPostExecute(result);
|
|
||||||
Listener exchangeView = exchangeViewRef.get();
|
|
||||||
if (result) {
|
|
||||||
Log.d(TAG, "yay! = " + Rate);
|
|
||||||
if (exchangeView != null) {
|
|
||||||
exchangeView.exchange(currencyA, currencyB, inverse ? (1 / Rate) : Rate);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "nay!");
|
|
||||||
if (exchangeView != null) {
|
|
||||||
exchangeView.exchangeFailed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "https://api.kraken.com/0/public/Ticker?pair=XMREUR"
|
|
||||||
String getExchangeRate(String fiat) {
|
|
||||||
String jsonResponse =
|
|
||||||
Helper.getUrl("https://api.kraken.com/0/public/Ticker?pair=XMR" + fiat);
|
|
||||||
if (jsonResponse == null) return null;
|
|
||||||
try {
|
|
||||||
JSONObject response = new JSONObject(jsonResponse);
|
|
||||||
JSONArray errors = response.getJSONArray("error");
|
|
||||||
Log.e(TAG, "errors=" + errors.toString());
|
|
||||||
if (errors.length() == 0) {
|
|
||||||
JSONObject result = response.getJSONObject("result");
|
|
||||||
JSONObject pair = result.getJSONObject("XXMRZ" + fiat);
|
|
||||||
JSONArray close = pair.getJSONArray("c");
|
|
||||||
String closePrice = close.getString(0);
|
|
||||||
Log.d(TAG, "closePrice=" + closePrice);
|
|
||||||
return closePrice;
|
|
||||||
}
|
|
||||||
} catch (JSONException ex) {
|
|
||||||
Log.e(TAG, ex.getLocalizedMessage());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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.layout;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.SendFragment;
|
||||||
|
|
||||||
|
public class SpendViewPager extends ViewPager {
|
||||||
|
|
||||||
|
public interface OnValidateFieldsListener {
|
||||||
|
boolean onValidateFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpendViewPager(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpendViewPager(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void next() {
|
||||||
|
int pos = getCurrentItem();
|
||||||
|
if (validateFields(pos)) {
|
||||||
|
setCurrentItem(pos + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void previous() {
|
||||||
|
setCurrentItem(getCurrentItem() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean allowSwipe = true;
|
||||||
|
|
||||||
|
public void allowSwipe(boolean allow) {
|
||||||
|
allowSwipe = allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validateFields(int position) {
|
||||||
|
OnValidateFieldsListener c = ((SendFragment.SpendPagerAdapter) getAdapter()).getFragment(position);
|
||||||
|
return c.onValidateFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onInterceptTouchEvent(MotionEvent event) {
|
||||||
|
if (allowSwipe) return super.onInterceptTouchEvent(event);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
if (allowSwipe) return super.onTouchEvent(event);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@@ -19,7 +19,6 @@ package com.m2049r.xmrwallet.layout;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -37,16 +36,12 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfoAdapter.ViewHolder> {
|
public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfoAdapter.ViewHolder> {
|
||||||
private static final String TAG = "TransactionInfoAdapter";
|
|
||||||
|
|
||||||
private final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
private final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
|
||||||
//static final int TX_RED = Color.rgb(255, 79, 65);
|
|
||||||
//static final int TX_GREEN = Color.rgb(54, 176, 91);
|
|
||||||
//static final int TX_PENDING = Color.rgb(72, 53, 176);
|
|
||||||
//static final int TX_FAILED = Color.rgb(208, 0, 255);
|
|
||||||
|
|
||||||
private int outboundColour;
|
private int outboundColour;
|
||||||
private int inboundColour;
|
private int inboundColour;
|
||||||
private int pendingColour;
|
private int pendingColour;
|
||||||
@@ -96,11 +91,11 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
// as the TransactionInfo items are always recreated, we cannot recycle
|
// as the TransactionInfo items are always recreated, we cannot recycle
|
||||||
this.infoItems.clear();
|
this.infoItems.clear();
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
Log.d(TAG, "setInfos " + data.size());
|
Timber.d("setInfos %s", data.size());
|
||||||
infoItems.addAll(data);
|
infoItems.addAll(data);
|
||||||
Collections.sort(infoItems);
|
Collections.sort(infoItems);
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "setInfos null");
|
Timber.d("setInfos null");
|
||||||
}
|
}
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@ package com.m2049r.xmrwallet.layout;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.v7.widget.PopupMenu;
|
import android.support.v7.widget.PopupMenu;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -38,8 +37,9 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.ViewHolder> {
|
public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.ViewHolder> {
|
||||||
private static final String TAG = "WalletInfoAdapter";
|
|
||||||
|
|
||||||
private final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
private final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
|
||||||
@@ -89,11 +89,11 @@ public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.Vi
|
|||||||
// as the WalletInfo items are always recreated, we cannot recycle
|
// as the WalletInfo items are always recreated, we cannot recycle
|
||||||
infoItems.clear();
|
infoItems.clear();
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
Log.d(TAG, "setInfos " + data.size());
|
Timber.d("setInfos %s", data.size());
|
||||||
infoItems.addAll(data);
|
infoItems.addAll(data);
|
||||||
Collections.sort(infoItems);
|
Collections.sort(infoItems);
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "setInfos null");
|
Timber.d("setInfos null");
|
||||||
}
|
}
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
@@ -103,6 +103,7 @@ public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.Vi
|
|||||||
final TextView tvAddress;
|
final TextView tvAddress;
|
||||||
final ImageButton ibOptions;
|
final ImageButton ibOptions;
|
||||||
WalletManager.WalletInfo infoItem;
|
WalletManager.WalletInfo infoItem;
|
||||||
|
boolean popupOpen = false;
|
||||||
|
|
||||||
ViewHolder(View itemView) {
|
ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
@@ -112,10 +113,12 @@ public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.Vi
|
|||||||
ibOptions.setOnClickListener(new View.OnClickListener() {
|
ibOptions.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
|
if (popupOpen) return;
|
||||||
//creating a popup menu
|
//creating a popup menu
|
||||||
PopupMenu popup = new PopupMenu(context, ibOptions);
|
PopupMenu popup = new PopupMenu(context, ibOptions);
|
||||||
//inflating menu from xml resource
|
//inflating menu from xml resource
|
||||||
popup.inflate(R.menu.list_context_menu);
|
popup.inflate(R.menu.list_context_menu);
|
||||||
|
popupOpen = true;
|
||||||
//adding click listener
|
//adding click listener
|
||||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -128,6 +131,12 @@ public class WalletInfoAdapter extends RecyclerView.Adapter<WalletInfoAdapter.Vi
|
|||||||
});
|
});
|
||||||
//displaying the popup
|
//displaying the popup
|
||||||
popup.show();
|
popup.show();
|
||||||
|
popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
|
||||||
|
@Override
|
||||||
|
public void onDismiss(PopupMenu menu) {
|
||||||
|
popupOpen = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -19,8 +19,6 @@ package com.m2049r.xmrwallet.model;
|
|||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.util.TxData;
|
|
||||||
|
|
||||||
public class Transfer implements Parcelable {
|
public class Transfer implements Parcelable {
|
||||||
public long amount;
|
public long amount;
|
||||||
public String address;
|
public String address;
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package com.m2049r.xmrwallet.model;
|
package com.m2049r.xmrwallet.model;
|
||||||
|
|
||||||
import android.util.Log;
|
import com.m2049r.xmrwallet.data.TxData;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -154,6 +154,10 @@ public class Wallet {
|
|||||||
|
|
||||||
public static native boolean isPaymentIdValid(String payment_id);
|
public static native boolean isPaymentIdValid(String payment_id);
|
||||||
|
|
||||||
|
public static boolean isAddressValid(String address) {
|
||||||
|
return isAddressValid(address, WalletManager.getInstance().isTestNet());
|
||||||
|
}
|
||||||
|
|
||||||
public static native boolean isAddressValid(String address, boolean isTestNet);
|
public static native boolean isAddressValid(String address, boolean isTestNet);
|
||||||
|
|
||||||
//TODO static static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error);
|
//TODO static static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error);
|
||||||
@@ -187,6 +191,15 @@ public class Wallet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PendingTransaction createTransaction(TxData txData) {
|
||||||
|
return createTransaction(
|
||||||
|
txData.getDestinationAddress(),
|
||||||
|
txData.getPaymentId(),
|
||||||
|
txData.getAmount(),
|
||||||
|
txData.getMixin(),
|
||||||
|
txData.getPriority());
|
||||||
|
}
|
||||||
|
|
||||||
public PendingTransaction createTransaction(String dst_addr, String payment_id,
|
public PendingTransaction createTransaction(String dst_addr, String payment_id,
|
||||||
long amount, int mixin_count,
|
long amount, int mixin_count,
|
||||||
PendingTransaction.Priority priority) {
|
PendingTransaction.Priority priority) {
|
||||||
|
@@ -16,21 +16,17 @@
|
|||||||
|
|
||||||
package com.m2049r.xmrwallet.model;
|
package com.m2049r.xmrwallet.model;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class WalletManager {
|
public class WalletManager {
|
||||||
private final static String TAG = "WalletManager";
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
System.loadLibrary("monerujo");
|
System.loadLibrary("monerujo");
|
||||||
@@ -54,7 +50,7 @@ public class WalletManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void manageWallet(Wallet wallet) {
|
private void manageWallet(Wallet wallet) {
|
||||||
Log.d(TAG, "Managing " + wallet.getName());
|
Timber.d("Managing %s", wallet.getName());
|
||||||
managedWallet = wallet;
|
managedWallet = wallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +64,7 @@ public class WalletManager {
|
|||||||
if (getWallet() != wallet) {
|
if (getWallet() != wallet) {
|
||||||
throw new IllegalStateException(wallet.getName() + " not under management!");
|
throw new IllegalStateException(wallet.getName() + " not under management!");
|
||||||
}
|
}
|
||||||
Log.d(TAG, "Unmanaging " + managedWallet.getName());
|
Timber.d("Unmanaging %s", managedWallet.getName());
|
||||||
managedWallet = null;
|
managedWallet = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,14 +161,14 @@ public class WalletManager {
|
|||||||
info.path = wallet.getParentFile();
|
info.path = wallet.getParentFile();
|
||||||
info.name = wallet.getName();
|
info.name = wallet.getName();
|
||||||
File addressFile = new File(info.path, info.name + ".address.txt");
|
File addressFile = new File(info.path, info.name + ".address.txt");
|
||||||
//Log.d(TAG, addressFile.getAbsolutePath());
|
//Timber.d(addressFile.getAbsolutePath());
|
||||||
info.address = "??????";
|
info.address = "??????";
|
||||||
BufferedReader addressReader = null;
|
BufferedReader addressReader = null;
|
||||||
try {
|
try {
|
||||||
addressReader = new BufferedReader(new FileReader(addressFile));
|
addressReader = new BufferedReader(new FileReader(addressFile));
|
||||||
info.address = addressReader.readLine();
|
info.address = addressReader.readLine();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Log.d(TAG, ex.getLocalizedMessage());
|
Timber.d(ex.getLocalizedMessage());
|
||||||
} finally {
|
} finally {
|
||||||
if (addressReader != null) {
|
if (addressReader != null) {
|
||||||
try {
|
try {
|
||||||
@@ -187,7 +183,7 @@ public class WalletManager {
|
|||||||
|
|
||||||
public List<WalletInfo> findWallets(File path) {
|
public List<WalletInfo> findWallets(File path) {
|
||||||
List<WalletInfo> wallets = new ArrayList<>();
|
List<WalletInfo> wallets = new ArrayList<>();
|
||||||
Log.d(TAG, "Scanning: " + path.getAbsolutePath());
|
Timber.d("Scanning: %s", path.getAbsolutePath());
|
||||||
File[] found = path.listFiles(new FilenameFilter() {
|
File[] found = path.listFiles(new FilenameFilter() {
|
||||||
public boolean accept(File dir, String filename) {
|
public boolean accept(File dir, String filename) {
|
||||||
return filename.endsWith(".keys");
|
return filename.endsWith(".keys");
|
||||||
@@ -210,14 +206,15 @@ public class WalletManager {
|
|||||||
|
|
||||||
public boolean isTestNet() {
|
public boolean isTestNet() {
|
||||||
if (daemonAddress == null) {
|
if (daemonAddress == null) {
|
||||||
|
return true;
|
||||||
// assume testnet not explicitly initialised
|
// assume testnet not explicitly initialised
|
||||||
throw new IllegalStateException("use setDaemon() to initialise daemon and net first!");
|
//throw new IllegalStateException("use setDaemon() to initialise daemon and net first!");
|
||||||
}
|
}
|
||||||
return testnet;
|
return testnet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDaemon(String address, boolean testnet, String username, String password) {
|
public void setDaemon(String address, boolean testnet, String username, String password) {
|
||||||
//Log.d(TAG, "SETDAEMON " + username + "/" + password + "/" + address);
|
//Timber.d("SETDAEMON " + username + "/" + password + "/" + address);
|
||||||
this.daemonAddress = address;
|
this.daemonAddress = address;
|
||||||
this.testnet = testnet;
|
this.testnet = testnet;
|
||||||
this.daemonUsername = username;
|
this.daemonUsername = username;
|
||||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user