1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-04 17:28:42 +02:00

Compare commits

...

48 Commits

Author SHA1 Message Date
m2049r
bafe05117b Update FAQ.md 2017-12-11 16:15:35 +01:00
m2049r
4b7c181040 drawable fix for < v24 2017-12-11 16:00:45 +01:00
m2049r
a3721ae784 new version number 2017-12-09 20:43:23 +01:00
m2049r
ae62c528aa Tweaks & Fixes (#153)
* clear error

* isAddressValid refactoring

* better numpad layout

* receive qr code as card

* scan integrated address
2017-12-09 20:38:01 +01:00
m2049r
e6522769d0 rename version 2017-12-07 20:39:50 +01:00
m2049r
cab93e8c5e store on exit wallet if not synced (#152) 2017-12-07 20:04:04 +01:00
m2049r
ac78ecb298 Create new wallets in app-private storage (#151)
* new version

* create new wallet in app-private storage
2017-12-07 19:55:01 +01:00
m2049r
51876f788f Bugfixes & UI tweaks (#149)
* cancel button + avoid crash if exchanging

* max check fix
2017-12-05 21:26:38 +01:00
m2049r
82c32d4442 support integrated address (excl. qr code) (#147)
UI & code tweaks
2017-12-05 07:48:59 +01:00
m2049r
22b4905828 new alpha version 2017-12-03 22:19:57 +01:00
m2049r
0cb8ece336 Rework of Send flow + refactoring (#146) 2017-12-03 22:17:28 +01:00
Stephan Hagios
d2429da044 Feature/timber logging (#143)
* Added Timber for logging

* Replaced Log calls with timber

* added timber to licenses list

* PR suggestions
2017-11-25 15:49:07 +01:00
Stephan Hagios
92d867fbaa Added okhttp to the license string (#142) 2017-11-23 22:05:44 +01:00
Stephan Hagios
a5e3986eb9 Merge pull request #141 from m2049r/refactor_okhttp
Use OkHttp to get exchange rates
2017-11-23 20:25:45 +01:00
m2049r
8f7f4ee9f9 changes based on review 2017-11-23 08:23:23 +01:00
m2049r
c23597066a use OkHttpClient to get exchange rates
test cases
2017-11-22 18:34:28 +01:00
m2049r
dab5e08910 use textVisiblePassword for password field (#139) 2017-11-19 20:25:20 +01:00
m2049r
c35deab283 zoom into qr code on touch (#140) 2017-11-19 20:25:02 +01:00
Stephan Hagios
7c36ccfd9c Merge pull request #137 from m2049r/layout-tweaks
Layout tweaks
2017-11-18 16:02:47 +01:00
Stephan Hagios
402d51ec6e Merge pull request #138 from m2049r/screenshot-tweak
Don't prevent screenshots in debug mode
2017-11-18 15:55:37 +01:00
m2049r
ca58211676 dont prevent screenshots in debug mode 2017-11-18 13:11:54 +01:00
m2049r
97c6ba5334 full width amount fields 2017-11-18 13:10:34 +01:00
m2049r
f1f2f250be qr code is now a button 2017-11-18 11:04:34 +01:00
m2049r
7b19e9a2bd wider amount field with % left/right padding 2017-11-18 10:19:16 +01:00
mattcode55
ed8010c92c Set FLAG_SECURE to disable screenshots (#134)
mattermost: https://taiga.getmonero.org/project/m2049r-monerujo/us/38

Sets FLAG_SECURE on all activities to prevent users accidentally
screenshotting sensitive information.
2017-11-16 19:14:53 +01:00
m2049r
41580e5519 upgrade m2049r/monero to monerujo-v0.11.1.0 (#127) 2017-11-11 15:39:42 +01:00
m2049r
1875e2df62 Bugfixes (#126)
* new domain

* InetSocketAddress.IllegalArgumentException

* white text for buttons

* tweak credit dialog

* prevent multiple popups
2017-11-11 08:02:13 +01:00
m2049r
347123d961 UI bugfixes (#120)
* better wallet load progress

new version

* dont start LoginFragment if is already started
2017-11-08 23:04:01 +01:00
m2049r
f5ad07c2b0 some bugfixes (#119)
* avoid IllegalStateException in rare cases

* clear error state on edit

* new version

* ignore error if fragment unloaded
2017-11-07 23:22:09 +01:00
m2049r
62695af9c6 layout correction + new version code 2017-11-05 01:01:36 +01:00
Stephan Hagios
3b1c3d564b Adjusted Layout files (#118)
* Adjusted layout files with correct sizes.

* Added password visibility toggle
2017-11-05 00:25:26 +01:00
Jonathan Cross
b28a140b48 FAQ improvements (#116) 2017-11-04 23:55:26 +01:00
m2049r
75bba4a091 remove e-notaion for android 5.0! (#117)
and new version
2017-11-04 23:54:49 +01:00
m2049r
cfb3c23003 hide receive button before wallet is loaded (#115) 2017-11-04 15:31:34 +01:00
m2049r
2cb87bab8e nodes help 2017-11-04 14:07:54 +01:00
m2049r
1ddc3d6b58 normal font for receiver 2017-11-04 13:45:21 +01:00
m2049r
2fa48d7441 more help & restyle reallysend button (#114) 2017-11-04 13:23:56 +01:00
m2049r
545367db90 Changes from Alpha Feedback (#113)
* fab covers whole screen

* avoid potential NPE

* bugfix - spinners crashed after scan

* Gunther only if no wallets

* clearQR on failed exchange, tweaks, gray

* refactor info dialogs

* added default testnet node

* FAQ: my testnet wallet is broken

* version code 36, version name 1.1.7
2017-11-04 10:17:20 +01:00
m2049r
d67e02cbcb Mostly Help "System" (#112)
* help & new exchange icon

* layout tweaks + removed nocopy icons

* sync help

* hide keyboard on spend

* QR Recieve => Receive

* menu tweaking

* use png logo for android < nougat

* gray generate

* position tweak in toolbar

* new exchange icon for wallet balance

* new About Dialog

* enable sending on mainnet

* new version 1.1.6

* dispose transaction on back

* remove unused onExchange method

* gray stuff + some tweaks

* new logo for qr
2017-11-04 00:43:24 +01:00
m2049r
d3beb7ca3f exchange & toolbar layout (#111) 2017-11-03 10:14:19 +01:00
m2049r
f951e1a621 abort exchange if amount is invalid 2017-11-03 01:20:59 +01:00
m2049r
0e187d3b20 version 2017-11-02 22:52:13 +01:00
m2049r
716b830b7b Tweaks based on alpha feedback (#110)
* donation+privacy policy screens + bugfixes

* opacity

* mnemonic left aligned

* smaller scan button

* spread out fabs

* doExchnage on lose focus of amount

* specify wallet create type
2017-11-02 22:48:20 +01:00
m2049r
4ac6a03d63 rename fresh wallet (no cachefile) (#109) 2017-11-02 11:46:03 +01:00
m2049r
7eb86ea618 tx details consistent with tx list (#107) 2017-11-01 20:33:58 +01:00
Stephan Hagios
4cfd166ed7 Adjusted visibility of fields and methods. (#102)
* Adjusted visibility of fields and methods.

* Adjusted visibility of fields and methods after rebase
2017-11-01 19:47:24 +01:00
m2049r
44f241f4ee fix progress dialog not showing (#106)
also, new version
2017-11-01 19:26:18 +01:00
m2049r
62b77fc987 no more animation because of OOMs (#105) 2017-11-01 10:56:47 +01:00
185 changed files with 7011 additions and 2813 deletions

1
.gitignore vendored
View File

@@ -7,3 +7,4 @@
/captures
.externalNativeBuild
.DS_Store
/app/release

View File

@@ -21,7 +21,6 @@ You may lose all your Moneroj if you use this App. Be cautious when spending on
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
### TODO
- review visibility of methods/classes
- more sensible error dialogs
### Issues / Pitfalls

View File

@@ -8,8 +8,8 @@ android {
applicationId "com.m2049r.xmrwallet"
minSdkVersion 21
targetSdkVersion 25
versionCode 29
versionName "1.1.2-alpha"
versionCode 51
versionName "1.2.11"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
@@ -43,28 +43,39 @@ dependencies {
compile 'com.android.support:cardview-v7:25.4.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
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 {
verify = [
'com.android.support:appcompat-v7:70551e62660db15b790c5275f56b9de4dd9407d1494d07c8f3dd5698f3638677',
'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:recyclerview-v7:a2fe121f9d01ed8980e97095b4a3fe9700a0aa0a7d4b0f8c594f765ad8455a0d',
'com.android.support:cardview-v7:f3fbbe1fcfdbec7333c6a2c516c5fd511a909d1975271818e268d6fe297d8c70',
'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:transition:848270144fb180efd2bf928a00ed176dbbc5290badfd638390ffba90088df8b3',
'com.android.support:support-compat:54019c63614ce08b02d7b9605490cd2b29ba5b2505f394a9517450b5f72b30ca',
'com.android.support:support-vector-drawable:077009d13882ee96f061e4bc2dbe7cce7ae1762d8297592a787ff741afbfb1f2',
'com.android.support:support-fragment:316d35d4d2d2902057efad104a73e4bdb50bee260a7075678185b8cd71170945',
'com.android.support:support-core-ui:e72ae29b823889686cff6fcb948d6745c2baf6d4c2af4fdffa1ec1e42e3833a3',
'com.android.support:support-media-compat:566a161d9cb0083ef62a53e46b71ce5b3d455b8635b1a0a4ae28d96d4b583de8',
'com.android.support:support-core-utils:34b8437dfa95ff28d29cf57ffa3b1354a9fa9bfe4059f0fd5ce2f5e4326a1748',
'com.android.support:support-core-ui:e72ae29b823889686cff6fcb948d6745c2baf6d4c2af4fdffa1ec1e42e3833a3',
'com.android.support:support-fragment:316d35d4d2d2902057efad104a73e4bdb50bee260a7075678185b8cd71170945',
'com.android.support:support-compat:54019c63614ce08b02d7b9605490cd2b29ba5b2505f394a9517450b5f72b30ca',
'com.android.support:support-annotations:a774272036941b4e912eb426d70c848bde7f06a3bf5fb491f75a427dc6595270',
'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
'me.dm7.barcodescanner:core:a5c8a704089b58029db166172ed8e55d756877d010a85a0b1c94fdc96ffb8f9a',
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
'com.squareup.okhttp3:okhttp:7265adbd6f028aade307f58569d814835cd02bc9beffb70c25f72c9de50d61c4',
]
}

View File

@@ -13,6 +13,7 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:name=".XmrWalletApplication"
android:theme="@style/MyMaterialTheme">
<activity

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

View File

@@ -22,7 +22,6 @@ import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.Fragment;
import android.text.InputType;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -33,14 +32,16 @@ import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
import com.m2049r.xmrwallet.widget.Toolbar;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
import java.io.File;
import timber.log.Timber;
public class GenerateFragment extends Fragment {
static final String TAG = "GenerateFragment";
static final String TYPE = "type";
static final String TYPE_NEW = "new";
@@ -48,16 +49,16 @@ public class GenerateFragment extends Fragment {
static final String TYPE_SEED = "seed";
static final String TYPE_VIEWONLY = "view";
TextInputLayout etWalletName;
TextInputLayout etWalletPassword;
TextInputLayout etWalletAddress;
TextInputLayout etWalletMnemonic;
TextInputLayout etWalletViewKey;
TextInputLayout etWalletSpendKey;
TextInputLayout etWalletRestoreHeight;
Button bGenerate;
private TextInputLayout etWalletName;
private TextInputLayout etWalletPassword;
private TextInputLayout etWalletAddress;
private TextInputLayout etWalletMnemonic;
private TextInputLayout etWalletViewKey;
private TextInputLayout etWalletSpendKey;
private TextInputLayout etWalletRestoreHeight;
private Button bGenerate;
String type = null;
private String type = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -365,8 +366,26 @@ public class GenerateFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume()");
activityCallback.setTitle(getString(R.string.generate_title));
Timber.d("onResume()");
activityCallback.setTitle(getString(R.string.generate_title) + " - " + getType());
activityCallback.setToolbarButton(Toolbar.BUTTON_BACK);
}
String getType() {
switch (type) {
case TYPE_KEY:
return getString(R.string.generate_wallet_type_key);
case TYPE_NEW:
return getString(R.string.generate_wallet_type_new);
case TYPE_SEED:
return getString(R.string.generate_wallet_type_seed);
case TYPE_VIEWONLY:
return getString(R.string.generate_wallet_type_view);
default:
Timber.e("unknown type %s", type);
return "?";
}
}
GenerateFragment.Listener activityCallback;
@@ -379,6 +398,9 @@ public class GenerateFragment extends Fragment {
void onGenerate(String name, String password, String address, String viewKey, String spendKey, long height);
void setTitle(String title);
void setToolbarButton(int type);
}
@Override
@@ -400,7 +422,21 @@ public class GenerateFragment extends Fragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.create_wallet_menu, menu);
switch (type) {
case TYPE_KEY:
inflater.inflate(R.menu.create_wallet_keys, menu);
break;
case TYPE_NEW:
inflater.inflate(R.menu.create_wallet_new, menu);
break;
case TYPE_SEED:
inflater.inflate(R.menu.create_wallet_seed, menu);
break;
case TYPE_VIEWONLY:
inflater.inflate(R.menu.create_wallet_view, menu);
break;
default:
}
super.onCreateOptionsMenu(menu, inflater);
}
}

View File

@@ -21,7 +21,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -35,14 +34,15 @@ import android.widget.ScrollView;
import android.widget.TextView;
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.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
import timber.log.Timber;
public class GenerateReviewFragment extends Fragment {
static final String TAG = "GenerateReviewFragment";
static final public String VIEW_TYPE_DETAILS = "details";
static final public String VIEW_TYPE_ACCEPT = "accept";
static final public String VIEW_TYPE_WALLET = "wallet";
@@ -103,18 +103,6 @@ public class GenerateReviewFragment extends Fragment {
copyAddress();
}
});
view.findViewById(R.id.bCopySeed).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nocopy();
}
});
view.findViewById(R.id.bCopySepndKey).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nocopy();
}
});
view.findViewById(R.id.bAdvancedInfo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -276,7 +264,7 @@ public class GenerateReviewFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume()");
Timber.d("onResume()");
String name = tvWalletName.getText().toString();
if (name.isEmpty()) name = null;
activityCallback.setTitle(name, getString(R.string.details_title));
@@ -305,5 +293,6 @@ public class GenerateReviewFragment extends Fragment {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.wallet_details_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,15 +18,12 @@ package com.m2049r.xmrwallet;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -46,28 +43,29 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
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.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.NodeList;
import com.m2049r.xmrwallet.widget.DropDownEditText;
import com.m2049r.xmrwallet.widget.Toolbar;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import timber.log.Timber;
public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInteractionListener,
View.OnClickListener {
private static final String TAG = "LoginFragment";
private WalletInfoAdapter adapter;
List<WalletManager.WalletInfo> walletList = new ArrayList<>();
List<WalletManager.WalletInfo> displayedList = new ArrayList<>();
ImageView ivGuntherWallets;
EditText etDummy;
ImageView ivGunther;
DropDownEditText etDaemonAddress;
ArrayAdapter<String> nodeAdapter;
@@ -114,7 +112,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
@Override
public void onPause() {
Log.d(TAG, "onPause()");
Timber.d("onPause()");
savePrefs();
super.onPause();
}
@@ -122,7 +120,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume()");
Timber.d("onResume()");
activityCallback.setTitle(null);
activityCallback.setToolbarButton(Toolbar.BUTTON_DONATE);
activityCallback.showNet(isTestnet());
@@ -131,11 +129,10 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
Timber.d("onCreateView");
View view = inflater.inflate(R.layout.fragment_login, container, false);
ivGuntherWallets = (ImageView) view.findViewById(R.id.ivGuntherWallets);
ivGunther = (ImageView) view.findViewById(R.id.ivGunther);
fabScreen = (FrameLayout) view.findViewById(R.id.fabScreen);
fab = (FloatingActionButton) view.findViewById(R.id.fab);
fabNew = (FloatingActionButton) view.findViewById(R.id.fabNew);
@@ -148,6 +145,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
fabKeyL = (RelativeLayout) view.findViewById(R.id.fabKeyL);
fabSeedL = (RelativeLayout) view.findViewById(R.id.fabSeedL);
fab_pulse = AnimationUtils.loadAnimation(getContext(), R.anim.fab_pulse);
fab_open_screen = AnimationUtils.loadAnimation(getContext(), R.anim.fab_open_screen);
fab_close_screen = AnimationUtils.loadAnimation(getContext(), R.anim.fab_close_screen);
fab_open = AnimationUtils.loadAnimation(getContext(), R.anim.fab_open);
@@ -213,25 +211,10 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
});
loadPrefs();
return view;
}
void showGunther() {
ivGuntherWallets.setImageResource(R.drawable.gunther_wallets);
final AnimationDrawable guntherWalletsAnim = (AnimationDrawable) ivGuntherWallets.getDrawable();
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
guntherWalletsAnim.start();
}
}, getResources().getInteger(R.integer.gunther_wallets_delay));
}
void normalGunther() {
ivGuntherWallets.setImageResource(R.drawable.gunther_wallets_00);
}
// Callbacks from WalletInfoAdapter
@Override
public void onInteraction(final View view, final WalletManager.WalletInfo infoItem) {
@@ -279,7 +262,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
}
public void loadList() {
Log.d(TAG, "loadList()");
Timber.d("loadList()");
WalletManager mgr = WalletManager.getInstance();
List<WalletManager.WalletInfo> walletInfos =
mgr.findWallets(activityCallback.getStorageRoot());
@@ -288,10 +271,18 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
filterList();
adapter.setInfos(displayedList);
adapter.notifyDataSetChanged();
// deal with Gunther & FAB animation
if (displayedList.isEmpty()) {
showGunther();
fab.startAnimation(fab_pulse);
if (ivGunther.getDrawable() == null) {
ivGunther.setImageResource(R.drawable.gunther_desaturated);
}
} else {
normalGunther();
fab.clearAnimation();
if (ivGunther.getDrawable() != null) {
ivGunther.setImageDrawable(null);
}
}
}
@@ -324,7 +315,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
}
public boolean onTestnetMenuItem() {
boolean lastState = testnet;//item.isChecked();
boolean lastState = testnet;
setNet(!lastState, true); // set and save
return !lastState;
}
@@ -345,10 +336,12 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
private static final String PREF_DAEMON_TESTNET = "daemon_testnet";
private static final String PREF_DAEMON_MAINNET = "daemon_mainnet";
//private static final String PREF_TESTNET = "testnet";
private static final String PREF_DAEMONLIST_MAINNET =
"node.moneroworld.com:18089;node.xmrbackb.one:18081;node.xmr.be:18081";
"node.moneroworld.com:18089;node.xmrbackb.one;node.xmr.be";
private static final String PREF_DAEMONLIST_TESTNET =
"testnet.xmrchain.net";
private NodeList daemonTestNet;
private NodeList daemonMainNet;
@@ -357,7 +350,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
SharedPreferences sharedPref = activityCallback.getPrefs();
daemonMainNet = new NodeList(sharedPref.getString(PREF_DAEMON_MAINNET, PREF_DAEMONLIST_MAINNET));
daemonTestNet = new NodeList(sharedPref.getString(PREF_DAEMON_TESTNET, ""));
daemonTestNet = new NodeList(sharedPref.getString(PREF_DAEMON_TESTNET, PREF_DAEMONLIST_TESTNET));
setNet(isTestnet(), false);
}
@@ -366,7 +359,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
}
void savePrefs(boolean usePreviousState) {
Log.d(TAG, "SAVE / " + usePreviousState);
Timber.d("SAVE / %s", usePreviousState);
// save the daemon address for the net
boolean testnet = isTestnet() ^ usePreviousState;
String daemon = getDaemon();
@@ -378,7 +371,6 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
SharedPreferences sharedPref = activityCallback.getPrefs();
SharedPreferences.Editor editor = sharedPref.edit();
//editor.putBoolean(PREF_TESTNET, testnet);
editor.putString(PREF_DAEMON_MAINNET, daemonMainNet.toString());
editor.putString(PREF_DAEMON_TESTNET, daemonTestNet.toString());
editor.apply();
@@ -389,7 +381,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
}
void setDaemon(NodeList nodeList) {
Log.d(TAG, "setDaemon() " + nodeList.toString());
Timber.d("setDaemon() %s", nodeList.toString());
String[] nodes = nodeList.getNodes().toArray(new String[0]);
nodeAdapter.clear();
nodeAdapter.addAll(nodes);
@@ -407,6 +399,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
private FrameLayout fabScreen;
private RelativeLayout fabNewL, fabViewL, fabKeyL, fabSeedL;
private Animation fab_open, fab_close, rotate_forward, rotate_backward, fab_open_screen, fab_close_screen;
private Animation fab_pulse;
public boolean isFabOpen() {
return isFabOpen;

View File

@@ -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();
}

View File

@@ -19,6 +19,7 @@ package com.m2049r.xmrwallet;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.TextInputLayout;
@@ -26,7 +27,6 @@ import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -46,30 +46,30 @@ import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
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.WalletManager;
import com.m2049r.xmrwallet.util.Helper;
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.Map;
import timber.log.Timber;
public class ReceiveFragment extends Fragment {
static final String TAG = "ReceiveFragment";
ProgressBar pbProgress;
TextView tvAddress;
TextInputLayout etPaymentId;
ExchangeView evAmount;
Button bPaymentId;
Button bGenerate;
ImageView qrCode;
EditText etDummy;
ImageButton bCopyAddress;
//String name;
private ProgressBar pbProgress;
private TextView tvAddress;
private TextInputLayout etPaymentId;
private ExchangeView evAmount;
private Button bPaymentId;
private TextView tvQrCode;
private ImageView qrCode;
private ImageView qrCodeFull;
private EditText etDummy;
private ImageButton bCopyAddress;
public interface Listener {
void setToolbarButton(int type);
@@ -91,7 +91,8 @@ public class ReceiveFragment extends Fragment {
evAmount = (ExchangeView) view.findViewById(R.id.evAmount);
bPaymentId = (Button) view.findViewById(R.id.bPaymentId);
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);
bCopyAddress = (ImageButton) view.findViewById(R.id.bCopyAddress);
@@ -108,25 +109,21 @@ public class ReceiveFragment extends Fragment {
evAmount.setOnNewAmountListener(new ExchangeView.OnNewAmountListener() {
@Override
public void onNewAmount(String xmr) {
Log.d(TAG, "new amount = " + xmr);
Timber.d("new amount = %s", xmr);
generateQr();
}
});
/*
evAmount.setOnAmountInvalidatedListener(new ExchangeView.OnAmountInvalidatedListener() {
@Override
public void onAmountInvalidated() {
clearQR();
}
});
evAmount.setOnFailedExchangeListener(new ExchangeView.OnFailedExchangeListener() {
@Override
public void onFailedExchange() {
Toast.makeText(getActivity(), getString(R.string.message_exchange_failed), Toast.LENGTH_LONG).show();
if (isAdded()) {
clearQR();
Toast.makeText(getActivity(), getString(R.string.message_exchange_failed), Toast.LENGTH_LONG).show();
}
}
});
*/
etPaymentId.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
@@ -152,7 +149,6 @@ public class ReceiveFragment extends Fragment {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
bPaymentId.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -164,22 +160,33 @@ public class ReceiveFragment extends Fragment {
}
});
bGenerate.setOnClickListener(new View.OnClickListener() {
qrCode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (checkPaymentId()) {
if (qrValid) {
qrCodeFull.setImageBitmap(((BitmapDrawable) qrCode.getDrawable()).getBitmap());
qrCodeFull.setVisibility(View.VISIBLE);
} else if (checkPaymentId()) {
evAmount.doExchange();
}
}
});
qrCodeFull.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
qrCodeFull.setImageBitmap(null);
qrCodeFull.setVisibility(View.GONE);
}
});
showProgress();
clearQR();
Bundle b = getArguments();
String address = b.getString("address");
String walletName = b.getString("name");
Log.d(TAG, "address=" + address + "/name=" + walletName);
Timber.d("%s/%s", address, walletName);
if (address == null) {
String path = b.getString("path");
String password = b.getString("password");
@@ -199,14 +206,17 @@ public class ReceiveFragment extends Fragment {
void clearQR() {
if (qrValid) {
qrCode.setImageBitmap(getMoneroLogo());
qrCode.setImageBitmap(null);
qrValid = false;
if (isLoaded)
tvQrCode.setVisibility(View.VISIBLE);
}
}
void setQR(Bitmap qr) {
qrCode.setImageBitmap(qr);
qrValid = true;
tvQrCode.setVisibility(View.INVISIBLE);
Helper.hideKeyboard(getActivity());
etDummy.requestFocus();
}
@@ -214,20 +224,21 @@ public class ReceiveFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume()");
Timber.d("onResume()");
listenerCallback.setToolbarButton(Toolbar.BUTTON_BACK);
listenerCallback.setSubtitle(getString(R.string.receive_title));
generateQr();
}
private boolean isLoaded = false;
private void show(String name, String address) {
Log.d(TAG, "name=" + name);
Timber.d("name=%s", name);
isLoaded = true;
listenerCallback.setTitle(name);
tvAddress.setText(address);
etPaymentId.setEnabled(true);
//etAmount.setEnabled(true);
bPaymentId.setEnabled(true);
bGenerate.setEnabled(true);
bCopyAddress.setEnabled(true);
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
hideProgress();
@@ -282,14 +293,14 @@ public class ReceiveFragment extends Fragment {
}
private void generateQr() {
Log.d(TAG, "GENQR");
Timber.d("GENQR");
String address = tvAddress.getText().toString();
String paymentId = etPaymentId.getEditText().getText().toString();
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())) {
clearQR();
Log.d(TAG, "CLEARQR");
Timber.d("CLEARQR");
return;
}
StringBuffer sb = new StringBuffer();
@@ -311,10 +322,11 @@ public class ReceiveFragment extends Fragment {
sb.append(ScannerFragment.QR_AMOUNT).append('=').append(xmrAmount);
}
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) {
setQR(qr);
Log.d(TAG, "SETQR");
Timber.d("SETQR");
etDummy.requestFocus();
Helper.hideKeyboard(getActivity());
}
@@ -345,7 +357,6 @@ public class ReceiveFragment extends Fragment {
return null;
}
// TODO check if we can sensibly cache some of this
private Bitmap addLogo(Bitmap qrBitmap) {
Bitmap logo = getMoneroLogo();
int qrWidth = qrBitmap.getWidth();
@@ -373,7 +384,7 @@ public class ReceiveFragment extends Fragment {
private Bitmap getMoneroLogo() {
if (logo == null) {
logo = Helper.getBitmap(getContext(), R.drawable.ic_monero_qr);
logo = Helper.getBitmap(getContext(), R.drawable.ic_monero_logo_b);
}
return logo;
}
@@ -399,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
public void onPause() {
Log.d(TAG, "onPause()");
Timber.d("onPause()");
super.onPause();
}
}

View File

@@ -20,7 +20,6 @@ import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -30,21 +29,21 @@ import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import me.dm7.barcodescanner.zxing.ZXingScannerView;
import timber.log.Timber;
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
static final String TAG = "ScannerFragment";
Listener activityCallback;
private OnScannedListener onScannedListener;
public interface Listener {
boolean onAddressScanned(String uri);
public interface OnScannedListener {
boolean onScanned(String uri);
}
private ZXingScannerView mScannerView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
Timber.d("onCreateView");
mScannerView = new ZXingScannerView(getActivity());
return mScannerView;
}
@@ -52,7 +51,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
Timber.d("onResume");
mScannerView.setResultHandler(this);
mScannerView.startCamera();
}
@@ -63,9 +62,8 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
@Override
public void handleResult(Result rawResult) {
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
(rawResult.getText().startsWith(QR_SCHEME))) {
if (activityCallback.onAddressScanned(rawResult.getText())) {
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE)) {
if (onScannedListener.onScanned(rawResult.getText())) {
return;
} else {
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
public void onPause() {
Log.d(TAG, "onPause");
Timber.d("onPause");
mScannerView.stopCamera();
super.onPause();
}
@@ -99,11 +97,11 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof Listener) {
this.activityCallback = (Listener) context;
if (context instanceof OnScannedListener) {
this.onScannedListener = (OnScannedListener) context;
} else {
throw new ClassCastException(context.toString()
+ " must implement Listener");
}
}
}
}

View 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

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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() {
}
}

View File

@@ -31,10 +31,10 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.m2049r.xmrwallet.layout.Toolbar;
import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Transfer;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.widget.Toolbar;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -44,7 +44,6 @@ import java.util.Set;
import java.util.TimeZone;
public class TxFragment extends Fragment {
static final String TAG = "TxFragment";
static public final String ARG_INFO = "info";
@@ -57,17 +56,17 @@ public class TxFragment extends Fragment {
TS_FORMATTER.setTimeZone(tz);
}
TextView tvTxTimestamp;
TextView tvTxId;
TextView tvTxKey;
TextView tvDestination;
TextView tvTxPaymentId;
TextView tvTxBlockheight;
TextView tvTxAmount;
TextView tvTxFee;
TextView tvTxTransfers;
TextView etTxNotes;
Button bTxNotes;
private TextView tvTxTimestamp;
private TextView tvTxId;
private TextView tvTxKey;
private TextView tvDestination;
private TextView tvTxPaymentId;
private TextView tvTxBlockheight;
private TextView tvTxAmount;
private TextView tvTxFee;
private TextView tvTxTransfers;
private TextView etTxNotes;
private Button bTxNotes;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -167,8 +166,7 @@ public class TxFragment extends Fragment {
sb.append("-");
}
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();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, sb.toString());
@@ -212,18 +210,20 @@ public class TxFragment extends Fragment {
}
String sign = (info.direction == TransactionInfo.Direction.Direction_In ? "+" : "-");
tvTxAmount.setText(sign + Wallet.getDisplayAmount(info.amount));
long realAmount = info.amount;
if (info.isPending) {
realAmount = realAmount - info.fee;
}
tvTxAmount.setText(sign + Wallet.getDisplayAmount(realAmount));
if ((info.fee > 0)) {
String fee = Wallet.getDisplayAmount(info.fee);
if (info.isPending) {
tvTxFee.setText(getString(R.string.tx_list_fee_pending, fee));
} else {
tvTxFee.setText(getString(R.string.tx_list_fee, fee));
}
tvTxFee.setText(getString(R.string.tx_list_fee, fee));
} else {
tvTxFee.setText(null);
tvTxFee.setVisibility(View.GONE);
}
if (info.isFailed) {
tvTxAmount.setText(getString(R.string.tx_list_amount_failed, Wallet.getDisplayAmount(info.amount)));
tvTxFee.setText(getString(R.string.tx_list_failed_text));
@@ -307,4 +307,4 @@ public class TxFragment extends Fragment {
+ " must implement Listener");
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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());
}
}
}

View 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);
}
}

View 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();
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.m2049r.xmrwallet.util;
package com.m2049r.xmrwallet.data;
import android.os.Parcel;
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
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,
String paymentId,
long amount,
@@ -35,11 +44,35 @@ public class TxData implements Parcelable {
this.priority = priority;
}
public String dst_addr;
public String paymentId;
public long amount;
public int mixin;
public PendingTransaction.Priority priority;
public long getFee() {
return 0L;
}
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
public void writeToParcel(Parcel out, int flags) {
@@ -87,7 +120,7 @@ public class TxData implements Parcelable {
sb.append(",mixin:");
sb.append(mixin);
sb.append(",priority:");
sb.append(priority.toString());
sb.append(String.valueOf(priority));
return sb.toString();
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2017 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet.dialog;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import com.m2049r.xmrwallet.BuildConfig;
import com.m2049r.xmrwallet.R;
public class AboutFragment extends DialogFragment {
static final String TAG = "AboutFragment";
public static AboutFragment newInstance() {
return new AboutFragment();
}
public static void display(FragmentManager fm) {
FragmentTransaction ft = fm.beginTransaction();
Fragment prev = fm.findFragmentByTag(TAG);
if (prev != null) {
ft.remove(prev);
}
AboutFragment.newInstance().show(ft, TAG);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_about, null);
((TextView) view.findViewById(R.id.tvHelp)).setText(Html.fromHtml(getString(R.string.about_licenses)));
((TextView) view.findViewById(R.id.tvVersion)).setText(getString(R.string.about_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view);
builder.setNegativeButton(R.string.about_close,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
return builder.create();
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2017 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet.dialog;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.util.Helper;
public class DonationFragment extends DialogFragment {
static final String TAG = "DonationFragment";
public static DonationFragment newInstance() {
return new DonationFragment();
}
public static void display(FragmentManager fm) {
FragmentTransaction ft = fm.beginTransaction();
Fragment prev = fm.findFragmentByTag(TAG);
if (prev != null) {
ft.remove(prev);
}
DonationFragment.newInstance().show(ft, TAG);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_donation, null);
((TextView) view.findViewById(R.id.tvCredits)).setText(Html.fromHtml(getString(R.string.donation_credits)));
(view.findViewById(R.id.bCopyAddress)).
setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_address),
((TextView) view.findViewById(R.id.tvWalletAddress)).getText().toString());
Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show();
}
});
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view);
builder.setNegativeButton(R.string.about_close,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
return builder.create();
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 Adam Speakman, m2049r
* <p>
/*
* Copyright (c) 2017 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
*
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,98 +16,57 @@
package com.m2049r.xmrwallet.dialog;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.m2049r.xmrwallet.R;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Based on LicensesFragment by Adam Speakman on 24/09/13.
* http://speakman.net.nz
*/
public class HelpFragment extends DialogFragment {
static final String TAG = "HelpFragment";
private static final String FRAGMENT_TAG = "com.m2049r.xmrwallet.dialog.HelpFragment";
private static final String HELP_ID = "HELP_ID";
private AsyncTask<Void, Void, String> loader;
public static HelpFragment newInstance(int helpResourceId) {
HelpFragment fragment = new HelpFragment();
Bundle bundle = new Bundle();
bundle.putInt(HELP_ID, helpResourceId);
fragment.setArguments(bundle);
return fragment;
}
/**
* @param fm A fragment manager instance used to display this LicensesFragment.
*/
public static void displayHelp(FragmentManager fm, int helpResourceId) {
public static void display(FragmentManager fm, int helpResourceId) {
FragmentTransaction ft = fm.beginTransaction();
Fragment prev = fm.findFragmentByTag(FRAGMENT_TAG);
Fragment prev = fm.findFragmentByTag(TAG);
if (prev != null) {
ft.remove(prev);
}
// Create and show the dialog.
DialogFragment newFragment = HelpFragment.newInstance(helpResourceId);
newFragment.show(ft, FRAGMENT_TAG);
HelpFragment.newInstance(helpResourceId).show(ft, TAG);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_help, null);
int helpId = 0;
Bundle arguments = getArguments();
if (arguments != null) {
helpId = arguments.getInt(HELP_ID);
}
if (helpId > 0)
loadHelp(helpId);
}
@Override
public void onDestroy() {
super.onDestroy();
if (loader != null) {
loader.cancel(true);
}
}
private WebView webView;
private ProgressBar progress;
@SuppressLint("InflateParams")
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View content = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_help, null);
webView = (WebView) content.findViewById(R.id.helpFragmentWebView);
progress = (ProgressBar) content.findViewById(R.id.helpFragmentProgress);
((TextView) view.findViewById(R.id.tvHelp)).setText(Html.fromHtml(getString(helpId)));
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(content);
builder.setView(view);
builder.setNegativeButton(R.string.about_close,
new DialogInterface.OnClickListener() {
@Override
@@ -115,47 +74,6 @@ public class HelpFragment extends DialogFragment {
dialog.dismiss();
}
});
return builder.create();
}
private void loadHelp(final int helpResourceId) {
// Load asynchronously in case of a very large file.
loader = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
InputStream rawResource = getActivity().getResources().openRawResource(helpResourceId);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(rawResource));
String line;
StringBuilder sb = new StringBuilder();
try {
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
bufferedReader.close();
} catch (IOException ex) {
Log.e(TAG, ex.getLocalizedMessage());
}
return sb.toString();
}
@Override
protected void onPostExecute(String licensesBody) {
super.onPostExecute(licensesBody);
if (getActivity() == null || isCancelled()) {
return;
}
progress.setVisibility(View.INVISIBLE);
webView.setVisibility(View.VISIBLE);
webView.loadDataWithBaseURL(null, licensesBody, "text/html", "utf-8", null);
loader = null;
}
}.execute();
}
}

View File

@@ -1,165 +0,0 @@
/**
* Copyright 2013 Adam Speakman, m2049r
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet.dialog;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.m2049r.xmrwallet.BuildConfig;
import com.m2049r.xmrwallet.R;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Created by Adam Speakman on 24/09/13.
* http://speakman.net.nz
*/
public class LicensesFragment extends DialogFragment {
static final String TAG = "LicensesFragment";
int versionCode = BuildConfig.VERSION_CODE;
String versionName = BuildConfig.VERSION_NAME;
private AsyncTask<Void, Void, String> mLicenseLoader;
private static final String FRAGMENT_TAG = "com.m2049r.xmrwalelt.dialog.LicensesFragment";
/**
* Creates a new instance of LicensesFragment with no Close button.
*
* @return A new licenses fragment.
*/
public static LicensesFragment newInstance() {
return new LicensesFragment();
}
/**
* Builds and displays a licenses fragment with no Close button. Requires
* "/res/raw/licenses.html" and "/res/layout/licenses_fragment.xml" to be
* present.
*
* @param fm A fragment manager instance used to display this LicensesFragment.
*/
public static void displayLicensesFragment(FragmentManager fm) {
FragmentTransaction ft = fm.beginTransaction();
Fragment prev = fm.findFragmentByTag(FRAGMENT_TAG);
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
// Create and show the dialog.
DialogFragment newFragment = LicensesFragment.newInstance();
newFragment.show(ft, FRAGMENT_TAG);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
loadLicenses();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mLicenseLoader != null) {
mLicenseLoader.cancel(true);
}
}
private WebView mWebView;
private ProgressBar mIndeterminateProgress;
@SuppressLint("InflateParams")
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View content = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_licenses, null);
mWebView = (WebView) content.findViewById(R.id.licensesFragmentWebView);
mIndeterminateProgress = (ProgressBar) content.findViewById(R.id.licensesFragmentIndeterminateProgress);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
TextView text = (TextView) content.findViewById(R.id.licensesFragmentText);
text.setText(getString(R.string.about_text, versionName, versionCode));
builder.setView(content);
builder.setNegativeButton(R.string.about_close,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
return builder.create();
}
private void loadLicenses() {
// Load asynchronously in case of a very large file.
mLicenseLoader = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
InputStream rawResource = getActivity().getResources().openRawResource(R.raw.licenses);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(rawResource));
String line;
StringBuilder sb = new StringBuilder();
try {
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
bufferedReader.close();
} catch (IOException ex) {
Log.e(TAG, ex.getLocalizedMessage());
}
return sb.toString();
}
@Override
protected void onPostExecute(String licensesBody) {
super.onPostExecute(licensesBody);
if (getActivity() == null || isCancelled()) {
return;
}
mIndeterminateProgress.setVisibility(View.INVISIBLE);
mWebView.setVisibility(View.VISIBLE);
mWebView.loadDataWithBaseURL(null, licensesBody, "text/html", "utf-8", null);
mLicenseLoader = null;
}
}.execute();
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2017 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet.dialog;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import com.m2049r.xmrwallet.R;
public class PrivacyFragment extends DialogFragment {
static final String TAG = "PrivacyFragment";
public static PrivacyFragment newInstance() {
return new PrivacyFragment();
}
public static void display(FragmentManager fm) {
FragmentTransaction ft = fm.beginTransaction();
Fragment prev = fm.findFragmentByTag(TAG);
if (prev != null) {
ft.remove(prev);
}
PrivacyFragment.newInstance().show(ft, TAG);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_privacy_policy, null);
((TextView) view.findViewById(R.id.tvCredits)).setText(Html.fromHtml(getString(R.string.privacy_policy)));
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view);
builder.setNegativeButton(R.string.about_close,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
return builder.create();
}
}

Some files were not shown because too many files have changed in this diff Show More