mirror of
https://github.com/m2049r/xmrwallet
synced 2025-09-07 11:35:59 +02:00
Compare commits
27 Commits
v0.8.0.2
...
v1.1.2-alp
Author | SHA1 | Date | |
---|---|---|---|
![]() |
03c5569f91 | ||
![]() |
7b1e6a89ba | ||
![]() |
ff8a3ee7c8 | ||
![]() |
dcbaa35b57 | ||
![]() |
3466116e2a | ||
![]() |
59e87e2bfe | ||
![]() |
e8b749af3b | ||
![]() |
f282f01edd | ||
![]() |
f16afdbb19 | ||
![]() |
ccacec9d0b | ||
![]() |
9ebacb8528 | ||
![]() |
49a9f84226 | ||
![]() |
91b4aaad60 | ||
![]() |
c4ce12ceff | ||
![]() |
96cf9ee95e | ||
![]() |
00852da9f7 | ||
![]() |
15b90e7ebc | ||
![]() |
e270b277a5 | ||
![]() |
2842a4042f | ||
![]() |
1614c0ab84 | ||
![]() |
dceca0e198 | ||
![]() |
94947de9ef | ||
![]() |
10ea6d8e0c | ||
![]() |
0d03b75785 | ||
![]() |
a3db07c6a7 | ||
![]() |
6678222202 | ||
![]() |
793d984200 |
1
.idea/.gitignore
generated
vendored
1
.idea/.gitignore
generated
vendored
@@ -1,2 +1,3 @@
|
|||||||
workspace.xml
|
workspace.xml
|
||||||
markdown-*
|
markdown-*
|
||||||
|
misc.xml
|
||||||
|
10
.idea/libraries/constraint_layout_1_0_2.xml
generated
10
.idea/libraries/constraint_layout_1_0_2.xml
generated
@@ -1,10 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="constraint-layout-1.0.2">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="file://$USER_HOME$/.android/build-cache/983cd9976ef510b2538361561f2ee91f1200f245/output/res" />
|
|
||||||
<root url="jar://$USER_HOME$/.android/build-cache/983cd9976ef510b2538361561f2ee91f1200f245/output/jars/classes.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="constraint-layout-solver-1.0.2">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$USER_HOME$/AppData/Local/Android/Sdk/extras/m2repository/com/android/support/constraint/constraint-layout-solver/1.0.2/constraint-layout-solver-1.0.2.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
10
.idea/libraries/core_1_9_8.xml
generated
10
.idea/libraries/core_1_9_8.xml
generated
@@ -1,10 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="core-1.9.8">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$USER_HOME$/.android/build-cache/db7eb580bfa6467818ef12c5f1fa42273b50aa3a/output/jars/classes.jar!/" />
|
|
||||||
<root url="file://$USER_HOME$/.android/build-cache/db7eb580bfa6467818ef12c5f1fa42273b50aa3a/output/res" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
11
.idea/libraries/core_3_3_0.xml
generated
11
.idea/libraries/core_3_3_0.xml
generated
@@ -1,11 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="core-3.3.0">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.zxing/core/3.3.0/73c49077166faa4c3c0059c5f583d1d7bd1475fe/core-3.3.0.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES>
|
|
||||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.zxing/core/3.3.0/39d966e052e28fc7d83793b02e0af97ccf955745/core-3.3.0-sources.jar!/" />
|
|
||||||
</SOURCES>
|
|
||||||
</library>
|
|
||||||
</component>
|
|
10
.idea/libraries/zxing_1_9_8.xml
generated
10
.idea/libraries/zxing_1_9_8.xml
generated
@@ -1,10 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="zxing-1.9.8">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$USER_HOME$/.android/build-cache/8d8f2e0e10c7af73321454f6fa481e8e5438e654/output/jars/classes.jar!/" />
|
|
||||||
<root url="file://$USER_HOME$/.android/build-cache/8d8f2e0e10c7af73321454f6fa481e8e5438e654/output/res" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
46
.idea/misc.xml
generated
46
.idea/misc.xml
generated
@@ -1,46 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="EntryPointsManager">
|
|
||||||
<entry_points version="2.0" />
|
|
||||||
</component>
|
|
||||||
<component name="NullableNotNullManager">
|
|
||||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
|
||||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
|
||||||
<option name="myNullables">
|
|
||||||
<value>
|
|
||||||
<list size="4">
|
|
||||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
|
||||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
|
||||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
|
||||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
|
||||||
</list>
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="myNotNulls">
|
|
||||||
<value>
|
|
||||||
<list size="4">
|
|
||||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
|
||||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
|
||||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
|
||||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
|
||||||
</list>
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
|
||||||
<OptionsSetting value="true" id="Add" />
|
|
||||||
<OptionsSetting value="true" id="Remove" />
|
|
||||||
<OptionsSetting value="true" id="Checkout" />
|
|
||||||
<OptionsSetting value="true" id="Update" />
|
|
||||||
<OptionsSetting value="true" id="Status" />
|
|
||||||
<OptionsSetting value="true" id="Edit" />
|
|
||||||
<ConfirmationsSetting value="0" id="Add" />
|
|
||||||
<ConfirmationsSetting value="0" id="Remove" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectType">
|
|
||||||
<option name="id" value="Android" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@@ -14,7 +14,7 @@ You may lose all your Moneroj if you use this App. Be cautious when spending on
|
|||||||
- Based off monero v0.11.0.0 with PR #2289 applied
|
- Based off monero v0.11.0.0 with PR #2289 applied
|
||||||
- currently only android32 (runs on 64-bit as well)
|
- currently only android32 (runs on 64-bit as well)
|
||||||
- works on the testnet & mainnet
|
- works on the testnet & mainnet
|
||||||
- takes forever to sync due to 32-bit architecture
|
- sync is slow due to 32-bit architecture
|
||||||
- use your own daemon - it's easy
|
- use your own daemon - it's easy
|
||||||
- screen stays on until first sync is complete
|
- screen stays on until first sync is complete
|
||||||
- saves wallet only on first sync and when sending transactions or editing notes
|
- saves wallet only on first sync and when sending transactions or editing notes
|
||||||
@@ -25,11 +25,13 @@ You may lose all your Moneroj if you use this App. Be cautious when spending on
|
|||||||
- more sensible error dialogs
|
- more sensible error dialogs
|
||||||
|
|
||||||
### Issues / Pitfalls
|
### Issues / Pitfalls
|
||||||
|
- The backups folder is now called "backups" and not ".backups" - which in most file explorers was a hidden folder
|
||||||
|
- Wallets are now created directly in the "monerujo" folder, and not in the ".new" folder as before
|
||||||
|
- You may want to check the old folders with a file browsing app and delete the ".new" and ".backups" folders AFTER moving neccessary wallet files to the new locations. Or simply make new backups from within Monerujo.
|
||||||
|
- Also note, that on some devices the backups will only be visible on a PC over USB after a reboot of the device (it's an Android bug/feature)
|
||||||
- Created wallets on a private testnet are unusable because the restore height is set to that
|
- Created wallets on a private testnet are unusable because the restore height is set to that
|
||||||
of the "real" testnet. After creating a new wallet, make a **new** one by recovering from the seed.
|
of the "real" testnet. After creating a new wallet, make a **new** one by recovering from the seed.
|
||||||
The official monero client shows the same behaviour.
|
The official monero client shows the same behaviour.
|
||||||
- In rare occasions the monero core code returns a wallet address with corrupted characters -
|
|
||||||
in these cases Monerujo crashes on purpose to make sure nothing bad happens
|
|
||||||
|
|
||||||
### HOW TO BUILD
|
### HOW TO BUILD
|
||||||
No need to build. Binaries are included:
|
No need to build. Binaries are included:
|
||||||
|
@@ -3,13 +3,13 @@ apply plugin: 'witness'
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 25
|
compileSdkVersion 25
|
||||||
buildToolsVersion "25.0.2"
|
buildToolsVersion '26.0.2'
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.m2049r.xmrwallet"
|
applicationId "com.m2049r.xmrwallet"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 25
|
targetSdkVersion 25
|
||||||
versionCode 15
|
versionCode 29
|
||||||
versionName "0.8.0.2"
|
versionName "1.1.2-alpha"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
package="com.m2049r.xmrwallet">
|
package="com.m2049r.xmrwallet">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 253 KiB |
File diff suppressed because it is too large
Load Diff
@@ -19,17 +19,26 @@ package com.m2049r.xmrwallet;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.ScrollView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
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.MoneroThreadPoolExecutor;
|
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||||
|
|
||||||
public class GenerateReviewFragment extends Fragment {
|
public class GenerateReviewFragment extends Fragment {
|
||||||
@@ -38,6 +47,8 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
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";
|
||||||
|
|
||||||
|
ScrollView scrollview;
|
||||||
|
|
||||||
ProgressBar pbProgress;
|
ProgressBar pbProgress;
|
||||||
TextView tvWalletName;
|
TextView tvWalletName;
|
||||||
TextView tvWalletPassword;
|
TextView tvWalletPassword;
|
||||||
@@ -45,14 +56,18 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
TextView tvWalletMnemonic;
|
TextView tvWalletMnemonic;
|
||||||
TextView tvWalletViewKey;
|
TextView tvWalletViewKey;
|
||||||
TextView tvWalletSpendKey;
|
TextView tvWalletSpendKey;
|
||||||
|
ImageButton bCopyAddress;
|
||||||
|
LinearLayout llAdvancedInfo;
|
||||||
|
Button bAdvancedInfo;
|
||||||
Button bAccept;
|
Button bAccept;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.gen_review_fragment, container, false);
|
View view = inflater.inflate(R.layout.fragment_review, container, false);
|
||||||
|
|
||||||
|
scrollview = (ScrollView) view.findViewById(R.id.scrollview);
|
||||||
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
|
pbProgress = (ProgressBar) view.findViewById(R.id.pbProgress);
|
||||||
tvWalletName = (TextView) view.findViewById(R.id.tvWalletName);
|
tvWalletName = (TextView) view.findViewById(R.id.tvWalletName);
|
||||||
tvWalletPassword = (TextView) view.findViewById(R.id.tvWalletPassword);
|
tvWalletPassword = (TextView) view.findViewById(R.id.tvWalletPassword);
|
||||||
@@ -60,6 +75,9 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
tvWalletViewKey = (TextView) view.findViewById(R.id.tvWalletViewKey);
|
tvWalletViewKey = (TextView) view.findViewById(R.id.tvWalletViewKey);
|
||||||
tvWalletSpendKey = (TextView) view.findViewById(R.id.tvWalletSpendKey);
|
tvWalletSpendKey = (TextView) view.findViewById(R.id.tvWalletSpendKey);
|
||||||
tvWalletMnemonic = (TextView) view.findViewById(R.id.tvWalletMnemonic);
|
tvWalletMnemonic = (TextView) view.findViewById(R.id.tvWalletMnemonic);
|
||||||
|
bCopyAddress = (ImageButton) view.findViewById(R.id.bCopyAddress);
|
||||||
|
bAdvancedInfo = (Button) view.findViewById(R.id.bAdvancedInfo);
|
||||||
|
llAdvancedInfo = (LinearLayout) view.findViewById(R.id.llAdvancedInfo);
|
||||||
|
|
||||||
bAccept = (Button) view.findViewById(R.id.bAccept);
|
bAccept = (Button) view.findViewById(R.id.bAccept);
|
||||||
|
|
||||||
@@ -73,6 +91,36 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
acceptWallet();
|
acceptWallet();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
view.findViewById(R.id.bCopyViewKey).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
copyViewKey();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
bCopyAddress.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
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) {
|
||||||
|
showAdvancedInfo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
showProgress();
|
showProgress();
|
||||||
|
|
||||||
@@ -85,6 +133,31 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copyViewKey() {
|
||||||
|
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_viewkey), tvWalletViewKey.getText().toString());
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.message_copy_viewkey), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyAddress() {
|
||||||
|
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_address), tvWalletAddress.getText().toString());
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nocopy() {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.message_nocopy), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void showAdvancedInfo() {
|
||||||
|
llAdvancedInfo.setVisibility(View.VISIBLE);
|
||||||
|
bAdvancedInfo.setVisibility(View.GONE);
|
||||||
|
scrollview.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
scrollview.fullScroll(ScrollView.FOCUS_DOWN);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
String type;
|
String type;
|
||||||
|
|
||||||
private void acceptWallet() {
|
private void acceptWallet() {
|
||||||
@@ -130,7 +203,7 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
address = wallet.getAddress();
|
address = wallet.getAddress();
|
||||||
seed = wallet.getSeed();
|
seed = wallet.getSeed();
|
||||||
viewKey = wallet.getSecretViewKey();
|
viewKey = wallet.getSecretViewKey();
|
||||||
spendKey = isWatchOnly ? getActivity().getString(R.string.watchonly_label) : wallet.getSecretSpendKey();
|
spendKey = isWatchOnly ? getActivity().getString(R.string.label_watchonly) : wallet.getSecretSpendKey();
|
||||||
isWatchOnly = wallet.isWatchOnly();
|
isWatchOnly = wallet.isWatchOnly();
|
||||||
if (closeWallet) wallet.close();
|
if (closeWallet) wallet.close();
|
||||||
return true;
|
return true;
|
||||||
@@ -139,6 +212,7 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Boolean result) {
|
protected void onPostExecute(Boolean result) {
|
||||||
super.onPostExecute(result);
|
super.onPostExecute(result);
|
||||||
|
if (!isAdded()) return; // never mind
|
||||||
tvWalletName.setText(name);
|
tvWalletName.setText(name);
|
||||||
if (result) {
|
if (result) {
|
||||||
if (type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT)) {
|
if (type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT)) {
|
||||||
@@ -150,9 +224,14 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
tvWalletMnemonic.setText(seed);
|
tvWalletMnemonic.setText(seed);
|
||||||
tvWalletViewKey.setText(viewKey);
|
tvWalletViewKey.setText(viewKey);
|
||||||
tvWalletSpendKey.setText(spendKey);
|
tvWalletSpendKey.setText(spendKey);
|
||||||
|
bAdvancedInfo.setVisibility(View.VISIBLE);
|
||||||
|
bCopyAddress.setEnabled(true);
|
||||||
|
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
|
||||||
|
activityCallback.setTitle(name, getString(R.string.details_title));
|
||||||
|
activityCallback.setToolbarButton(
|
||||||
|
GenerateReviewFragment.VIEW_TYPE_ACCEPT.equals(type) ? Toolbar.BUTTON_NONE : Toolbar.BUTTON_BACK);
|
||||||
} else {
|
} else {
|
||||||
// TODO show proper error message
|
// TODO show proper error message and/or end the fragment?
|
||||||
// TODO end the fragment
|
|
||||||
tvWalletAddress.setText(status.toString());
|
tvWalletAddress.setText(status.toString());
|
||||||
tvWalletMnemonic.setText(status.toString());
|
tvWalletMnemonic.setText(status.toString());
|
||||||
tvWalletViewKey.setText(status.toString());
|
tvWalletViewKey.setText(status.toString());
|
||||||
@@ -162,41 +241,69 @@ public class GenerateReviewFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateReviewFragment.Listener acceptCallback = null;
|
Listener activityCallback = null;
|
||||||
GenerateReviewFragment.ListenerWithWallet walletCallback = null;
|
AcceptListener acceptCallback = null;
|
||||||
|
ListenerWithWallet walletCallback = null;
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
|
void setTitle(String title, String subtitle);
|
||||||
|
|
||||||
|
void setToolbarButton(int type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface AcceptListener {
|
||||||
void onAccept(String name, String password);
|
void onAccept(String name, String password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ListenerWithWallet {
|
public interface ListenerWithWallet {
|
||||||
Wallet getWallet();
|
Wallet getWallet();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
if (context instanceof GenerateReviewFragment.Listener) {
|
if (context instanceof Listener) {
|
||||||
this.acceptCallback = (GenerateReviewFragment.Listener) context;
|
this.activityCallback = (Listener) context;
|
||||||
} else if (context instanceof GenerateReviewFragment.ListenerWithWallet) {
|
}
|
||||||
this.walletCallback = (GenerateReviewFragment.ListenerWithWallet) context;
|
if (context instanceof AcceptListener) {
|
||||||
} else {
|
this.acceptCallback = (AcceptListener) context;
|
||||||
throw new ClassCastException(context.toString()
|
}
|
||||||
+ " must implement Listener");
|
if (context instanceof ListenerWithWallet) {
|
||||||
|
this.walletCallback = (ListenerWithWallet) context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
Log.d(TAG, "onResume()");
|
||||||
|
String name = tvWalletName.getText().toString();
|
||||||
|
if (name.isEmpty()) name = null;
|
||||||
|
activityCallback.setTitle(name, getString(R.string.details_title));
|
||||||
|
activityCallback.setToolbarButton(
|
||||||
|
GenerateReviewFragment.VIEW_TYPE_ACCEPT.equals(type) ? Toolbar.BUTTON_NONE : Toolbar.BUTTON_BACK);
|
||||||
|
}
|
||||||
|
|
||||||
public void showProgress() {
|
public void showProgress() {
|
||||||
pbProgress.setIndeterminate(true);
|
|
||||||
pbProgress.setVisibility(View.VISIBLE);
|
pbProgress.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hideProgress() {
|
public void hideProgress() {
|
||||||
pbProgress.setVisibility(View.INVISIBLE);
|
pbProgress.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean backOk() {
|
boolean backOk() {
|
||||||
return !type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT);
|
return !type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.wallet_details_menu, menu);
|
||||||
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,6 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.google.zxing.BarcodeFormat;
|
import com.google.zxing.BarcodeFormat;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
import com.m2049r.xmrwallet.util.BarcodeData;
|
|
||||||
|
|
||||||
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
import me.dm7.barcodescanner.zxing.ZXingScannerView;
|
||||||
|
|
||||||
@@ -64,7 +63,6 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleResult(Result rawResult) {
|
public void handleResult(Result rawResult) {
|
||||||
//Log.d(TAG, rawResult.getBarcodeFormat().toString() + "/" + rawResult.getText());
|
|
||||||
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
|
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE) &&
|
||||||
(rawResult.getText().startsWith(QR_SCHEME))) {
|
(rawResult.getText().startsWith(QR_SCHEME))) {
|
||||||
if (activityCallback.onAddressScanned(rawResult.getText())) {
|
if (activityCallback.onAddressScanned(rawResult.getText())) {
|
||||||
@@ -101,7 +99,6 @@ 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);
|
||||||
//Log.d(TAG, "attaching scan");
|
|
||||||
if (context instanceof Listener) {
|
if (context instanceof Listener) {
|
||||||
this.activityCallback = (Listener) context;
|
this.activityCallback = (Listener) context;
|
||||||
} else {
|
} else {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -16,19 +16,22 @@
|
|||||||
|
|
||||||
package com.m2049r.xmrwallet;
|
package com.m2049r.xmrwallet;
|
||||||
|
|
||||||
import android.content.ClipData;
|
|
||||||
import android.content.ClipboardManager;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
|
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;
|
||||||
@@ -64,14 +67,13 @@ public class TxFragment extends Fragment {
|
|||||||
TextView tvTxFee;
|
TextView tvTxFee;
|
||||||
TextView tvTxTransfers;
|
TextView tvTxTransfers;
|
||||||
TextView etTxNotes;
|
TextView etTxNotes;
|
||||||
Button bCopy;
|
|
||||||
Button bTxNotes;
|
Button bTxNotes;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.tx_fragment, container, false);
|
View view = inflater.inflate(R.layout.fragment_tx_info, container, false);
|
||||||
|
|
||||||
tvTxTimestamp = (TextView) view.findViewById(R.id.tvTxTimestamp);
|
tvTxTimestamp = (TextView) view.findViewById(R.id.tvTxTimestamp);
|
||||||
tvTxId = (TextView) view.findViewById(R.id.tvTxId);
|
tvTxId = (TextView) view.findViewById(R.id.tvTxId);
|
||||||
@@ -83,18 +85,10 @@ public class TxFragment extends Fragment {
|
|||||||
tvTxFee = (TextView) view.findViewById(R.id.tvTxFee);
|
tvTxFee = (TextView) view.findViewById(R.id.tvTxFee);
|
||||||
tvTxTransfers = (TextView) view.findViewById(R.id.tvTxTransfers);
|
tvTxTransfers = (TextView) view.findViewById(R.id.tvTxTransfers);
|
||||||
etTxNotes = (TextView) view.findViewById(R.id.etTxNotes);
|
etTxNotes = (TextView) view.findViewById(R.id.etTxNotes);
|
||||||
bCopy = (Button) view.findViewById(R.id.bCopy);
|
|
||||||
bTxNotes = (Button) view.findViewById(R.id.bTxNotes);
|
bTxNotes = (Button) view.findViewById(R.id.bTxNotes);
|
||||||
|
|
||||||
etTxNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
etTxNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
|
||||||
|
|
||||||
bCopy.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
copyToClipboard();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bTxNotes.setOnClickListener(new View.OnClickListener() {
|
bTxNotes.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@@ -119,28 +113,35 @@ public class TxFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void copyToClipboard() {
|
void shareTxInfo() {
|
||||||
if (this.info == null) return;
|
if (this.info == null) return;
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append(getString(R.string.tx_address)).append(": ");
|
|
||||||
sb.append(activityCallback.getWalletAddress()).append("\n");
|
sb.append(getString(R.string.tx_timestamp)).append(":\n");
|
||||||
sb.append(getString(R.string.tx_id)).append(": ");
|
sb.append(TS_FORMATTER.format(new Date(info.timestamp * 1000))).append("\n\n");
|
||||||
sb.append(info.hash).append("\n");
|
|
||||||
sb.append(getString(R.string.tx_key)).append(": ");
|
sb.append(getString(R.string.tx_amount)).append(":\n");
|
||||||
sb.append(info.txKey.isEmpty() ? "-" : info.txKey).append("\n");
|
|
||||||
sb.append(getString(R.string.tx_paymentId)).append(": ");
|
|
||||||
sb.append(info.paymentId).append("\n");
|
|
||||||
sb.append(getString(R.string.tx_amount)).append(": ");
|
|
||||||
sb.append((info.direction == TransactionInfo.Direction.Direction_In ? "+" : "-"));
|
sb.append((info.direction == TransactionInfo.Direction.Direction_In ? "+" : "-"));
|
||||||
sb.append(Wallet.getDisplayAmount(info.amount)).append("\n");
|
sb.append(Wallet.getDisplayAmount(info.amount)).append("\n");
|
||||||
sb.append(getString(R.string.tx_fee)).append(": ");
|
sb.append(getString(R.string.tx_fee)).append(":\n");
|
||||||
sb.append(Wallet.getDisplayAmount(info.fee)).append("\n");
|
sb.append(Wallet.getDisplayAmount(info.fee)).append("\n\n");
|
||||||
sb.append(getString(R.string.tx_notes)).append(": ");
|
|
||||||
|
sb.append(getString(R.string.tx_notes)).append(":\n");
|
||||||
String oneLineNotes = info.notes.replace("\n", " ; ");
|
String oneLineNotes = info.notes.replace("\n", " ; ");
|
||||||
sb.append(oneLineNotes.isEmpty() ? "-" : oneLineNotes).append("\n");
|
sb.append(oneLineNotes.isEmpty() ? "-" : oneLineNotes).append("\n\n");
|
||||||
sb.append(getString(R.string.tx_timestamp)).append(": ");
|
|
||||||
sb.append(TS_FORMATTER.format(new Date(info.timestamp * 1000))).append("\n");
|
sb.append(getString(R.string.tx_destination)).append(":\n");
|
||||||
sb.append(getString(R.string.tx_blockheight)).append(": ");
|
sb.append(tvDestination.getText()).append("\n\n");
|
||||||
|
|
||||||
|
sb.append(getString(R.string.tx_paymentId)).append(":\n");
|
||||||
|
sb.append(info.paymentId).append("\n\n");
|
||||||
|
|
||||||
|
sb.append(getString(R.string.tx_id)).append(":\n");
|
||||||
|
sb.append(info.hash).append("\n");
|
||||||
|
sb.append(getString(R.string.tx_key)).append(":\n");
|
||||||
|
sb.append(info.txKey.isEmpty() ? "-" : info.txKey).append("\n\n");
|
||||||
|
|
||||||
|
sb.append(getString(R.string.tx_blockheight)).append(":\n");
|
||||||
if (info.isFailed) {
|
if (info.isFailed) {
|
||||||
sb.append(getString(R.string.tx_failed)).append("\n");
|
sb.append(getString(R.string.tx_failed)).append("\n");
|
||||||
} else if (info.isPending) {
|
} else if (info.isPending) {
|
||||||
@@ -148,7 +149,9 @@ public class TxFragment extends Fragment {
|
|||||||
} else {
|
} else {
|
||||||
sb.append(info.blockheight).append("\n");
|
sb.append(info.blockheight).append("\n");
|
||||||
}
|
}
|
||||||
sb.append(getString(R.string.tx_transfers)).append(": ");
|
sb.append("\n");
|
||||||
|
|
||||||
|
sb.append(getString(R.string.tx_transfers)).append(":\n");
|
||||||
if (info.transfers != null) {
|
if (info.transfers != null) {
|
||||||
boolean comma = false;
|
boolean comma = false;
|
||||||
for (Transfer transfer : info.transfers) {
|
for (Transfer transfer : info.transfers) {
|
||||||
@@ -163,12 +166,14 @@ public class TxFragment extends Fragment {
|
|||||||
} else {
|
} else {
|
||||||
sb.append("-");
|
sb.append("-");
|
||||||
}
|
}
|
||||||
sb.append("\n");
|
sb.append("\n\n");
|
||||||
ClipboardManager clipboardManager = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
|
//Helper.clipBoardCopy(getActivity(), getString(R.string.tx_copy_label), sb.toString());
|
||||||
ClipData clip = ClipData.newPlainText(getString(R.string.tx_copy_label), sb.toString());
|
//Toast.makeText(getActivity(), getString(R.string.tx_copy_message), Toast.LENGTH_SHORT).show();
|
||||||
clipboardManager.setPrimaryClip(clip);
|
Intent sendIntent = new Intent();
|
||||||
Toast.makeText(getActivity(), getString(R.string.tx_copy_message), Toast.LENGTH_SHORT).show();
|
sendIntent.setAction(Intent.ACTION_SEND);
|
||||||
//Log.d(TAG, sb.toString());
|
sendIntent.putExtra(Intent.EXTRA_TEXT, sb.toString());
|
||||||
|
sendIntent.setType("text/plain");
|
||||||
|
startActivity(Intent.createChooser(sendIntent, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionInfo info = null;
|
TransactionInfo info = null;
|
||||||
@@ -176,17 +181,24 @@ public class TxFragment extends Fragment {
|
|||||||
void loadNotes(TransactionInfo info) {
|
void loadNotes(TransactionInfo info) {
|
||||||
if (info.notes == null) {
|
if (info.notes == null) {
|
||||||
info.notes = activityCallback.getTxNotes(info.hash);
|
info.notes = activityCallback.getTxNotes(info.hash);
|
||||||
//Log.d(TAG, "NOTES:" + info.notes + ":");
|
|
||||||
}
|
}
|
||||||
etTxNotes.setText(info.notes);
|
etTxNotes.setText(info.notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setTxColour(int clr) {
|
||||||
|
tvTxAmount.setTextColor(clr);
|
||||||
|
tvTxFee.setTextColor(clr);
|
||||||
|
}
|
||||||
|
|
||||||
private void show(TransactionInfo info) {
|
private void show(TransactionInfo info) {
|
||||||
if (info.txKey == null) {
|
if (info.txKey == null) {
|
||||||
info.txKey = activityCallback.getTxKey(info.hash);
|
info.txKey = activityCallback.getTxKey(info.hash);
|
||||||
//Log.d(TAG, "TXKEY:" + info.txKey + ":");
|
|
||||||
}
|
}
|
||||||
loadNotes(info);
|
loadNotes(info);
|
||||||
|
|
||||||
|
activityCallback.setSubtitle(getString(R.string.tx_title));
|
||||||
|
activityCallback.setToolbarButton(Toolbar.BUTTON_BACK);
|
||||||
|
|
||||||
tvTxTimestamp.setText(TS_FORMATTER.format(new Date(info.timestamp * 1000)));
|
tvTxTimestamp.setText(TS_FORMATTER.format(new Date(info.timestamp * 1000)));
|
||||||
tvTxId.setText(info.hash);
|
tvTxId.setText(info.hash);
|
||||||
tvTxKey.setText(info.txKey.isEmpty() ? "-" : info.txKey);
|
tvTxKey.setText(info.txKey.isEmpty() ? "-" : info.txKey);
|
||||||
@@ -199,8 +211,30 @@ public class TxFragment extends Fragment {
|
|||||||
tvTxBlockheight.setText("" + info.blockheight);
|
tvTxBlockheight.setText("" + info.blockheight);
|
||||||
}
|
}
|
||||||
String sign = (info.direction == TransactionInfo.Direction.Direction_In ? "+" : "-");
|
String sign = (info.direction == TransactionInfo.Direction.Direction_In ? "+" : "-");
|
||||||
|
|
||||||
tvTxAmount.setText(sign + Wallet.getDisplayAmount(info.amount));
|
tvTxAmount.setText(sign + Wallet.getDisplayAmount(info.amount));
|
||||||
tvTxFee.setText(Wallet.getDisplayAmount(info.fee));
|
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));
|
||||||
|
}
|
||||||
|
} 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));
|
||||||
|
setTxColour(ContextCompat.getColor(getContext(), R.color.tx_failed));
|
||||||
|
} else if (info.isPending) {
|
||||||
|
setTxColour(ContextCompat.getColor(getContext(), R.color.tx_pending));
|
||||||
|
} else if (info.direction == TransactionInfo.Direction.Direction_In) {
|
||||||
|
setTxColour(ContextCompat.getColor(getContext(), R.color.tx_green));
|
||||||
|
} else {
|
||||||
|
setTxColour(ContextCompat.getColor(getContext(), R.color.tx_red));
|
||||||
|
}
|
||||||
Set<String> destinations = new HashSet<>();
|
Set<String> destinations = new HashSet<>();
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
StringBuffer dstSb = new StringBuffer();
|
StringBuffer dstSb = new StringBuffer();
|
||||||
@@ -232,10 +266,21 @@ public class TxFragment extends Fragment {
|
|||||||
tvTxTransfers.setText(sb.toString());
|
tvTxTransfers.setText(sb.toString());
|
||||||
tvDestination.setText(dstSb.toString());
|
tvDestination.setText(dstSb.toString());
|
||||||
this.info = info;
|
this.info = info;
|
||||||
bCopy.setEnabled(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TxFragment.Listener activityCallback;
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.tx_info_menu, menu);
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
}
|
||||||
|
|
||||||
|
Listener activityCallback;
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
String getWalletAddress();
|
String getWalletAddress();
|
||||||
@@ -246,6 +291,10 @@ public class TxFragment extends Fragment {
|
|||||||
|
|
||||||
void onSetNote(String txId, String notes);
|
void onSetNote(String txId, String notes);
|
||||||
|
|
||||||
|
void setToolbarButton(int type);
|
||||||
|
|
||||||
|
void setSubtitle(String subtitle);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
161
app/src/main/java/com/m2049r/xmrwallet/dialog/HelpFragment.java
Normal file
161
app/src/main/java/com/m2049r/xmrwallet/dialog/HelpFragment.java
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
/**
|
||||||
|
* 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 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) {
|
||||||
|
FragmentTransaction ft = fm.beginTransaction();
|
||||||
|
Fragment prev = fm.findFragmentByTag(FRAGMENT_TAG);
|
||||||
|
if (prev != null) {
|
||||||
|
ft.remove(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and show the dialog.
|
||||||
|
DialogFragment newFragment = HelpFragment.newInstance(helpResourceId);
|
||||||
|
newFragment.show(ft, FRAGMENT_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
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);
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
|
|
||||||
|
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 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();
|
||||||
|
}
|
||||||
|
}
|
@@ -14,12 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.m2049r.xmrwallet.license;
|
package com.m2049r.xmrwallet.dialog;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
@@ -27,11 +22,11 @@ import android.app.Dialog;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
//TODO If you don't support Android 2.x, you should use the non-support version!
|
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
@@ -41,18 +36,23 @@ import android.widget.TextView;
|
|||||||
import com.m2049r.xmrwallet.BuildConfig;
|
import com.m2049r.xmrwallet.BuildConfig;
|
||||||
import com.m2049r.xmrwallet.R;
|
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.
|
* Created by Adam Speakman on 24/09/13.
|
||||||
* http://speakman.net.nz
|
* http://speakman.net.nz
|
||||||
*/
|
*/
|
||||||
public class LicensesFragment extends DialogFragment {
|
public class LicensesFragment extends DialogFragment {
|
||||||
|
static final String TAG = "LicensesFragment";
|
||||||
int versionCode = BuildConfig.VERSION_CODE;
|
int versionCode = BuildConfig.VERSION_CODE;
|
||||||
String versionName = BuildConfig.VERSION_NAME;
|
String versionName = BuildConfig.VERSION_NAME;
|
||||||
|
|
||||||
private AsyncTask<Void, Void, String> mLicenseLoader;
|
private AsyncTask<Void, Void, String> mLicenseLoader;
|
||||||
|
|
||||||
private static final String FRAGMENT_TAG = "nz.net.speakman.androidlicensespage.LicensesFragment";
|
private static final String FRAGMENT_TAG = "com.m2049r.xmrwalelt.dialog.LicensesFragment";
|
||||||
private static final String KEY_SHOW_CLOSE_BUTTON = "keyShowCloseButton";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of LicensesFragment with no Close button.
|
* Creates a new instance of LicensesFragment with no Close button.
|
||||||
@@ -63,22 +63,6 @@ public class LicensesFragment extends DialogFragment {
|
|||||||
return new LicensesFragment();
|
return new LicensesFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance of LicensesFragment with an optional Close button.
|
|
||||||
*
|
|
||||||
* @param showCloseButton Whether to show a Close button at the bottom of the dialog.
|
|
||||||
* @return A new licenses fragment.
|
|
||||||
*/
|
|
||||||
public static LicensesFragment newInstance(boolean showCloseButton) {
|
|
||||||
LicensesFragment fragment = new LicensesFragment();
|
|
||||||
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putBoolean(KEY_SHOW_CLOSE_BUTTON, showCloseButton);
|
|
||||||
fragment.setArguments(bundle);
|
|
||||||
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds and displays a licenses fragment with no Close button. Requires
|
* Builds and displays a licenses fragment with no Close button. Requires
|
||||||
* "/res/raw/licenses.html" and "/res/layout/licenses_fragment.xml" to be
|
* "/res/raw/licenses.html" and "/res/layout/licenses_fragment.xml" to be
|
||||||
@@ -99,27 +83,6 @@ public class LicensesFragment extends DialogFragment {
|
|||||||
newFragment.show(ft, FRAGMENT_TAG);
|
newFragment.show(ft, FRAGMENT_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds and displays a licenses fragment with or without a 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.
|
|
||||||
* @param showCloseButton Whether to show a Close button at the bottom of the dialog.
|
|
||||||
*/
|
|
||||||
public static void displayLicensesFragment(FragmentManager fm, boolean showCloseButton) {
|
|
||||||
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(showCloseButton);
|
|
||||||
newFragment.show(ft, FRAGMENT_TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
@@ -140,22 +103,15 @@ public class LicensesFragment extends DialogFragment {
|
|||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
View content = LayoutInflater.from(getActivity()).inflate(R.layout.licenses_fragment, null);
|
View content = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_licenses, null);
|
||||||
mWebView = (WebView) content.findViewById(R.id.licensesFragmentWebView);
|
mWebView = (WebView) content.findViewById(R.id.licensesFragmentWebView);
|
||||||
mIndeterminateProgress = (ProgressBar) content.findViewById(R.id.licensesFragmentIndeterminateProgress);
|
mIndeterminateProgress = (ProgressBar) content.findViewById(R.id.licensesFragmentIndeterminateProgress);
|
||||||
|
|
||||||
boolean showCloseButton = false;
|
|
||||||
Bundle arguments = getArguments();
|
|
||||||
if (arguments != null) {
|
|
||||||
showCloseButton = arguments.getBoolean(KEY_SHOW_CLOSE_BUTTON);
|
|
||||||
}
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
TextView text = (TextView) content.findViewById(R.id.text);
|
TextView text = (TextView) content.findViewById(R.id.licensesFragmentText);
|
||||||
text.setText(getString(R.string.about_text, versionName, versionCode));
|
text.setText(getString(R.string.about_text, versionName, versionCode));
|
||||||
|
|
||||||
builder.setView(content);
|
builder.setView(content);
|
||||||
if (showCloseButton) {
|
|
||||||
builder.setNegativeButton(R.string.about_close,
|
builder.setNegativeButton(R.string.about_close,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -163,7 +119,6 @@ public class LicensesFragment extends DialogFragment {
|
|||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
@@ -186,8 +141,8 @@ public class LicensesFragment extends DialogFragment {
|
|||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
bufferedReader.close();
|
bufferedReader.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException ex) {
|
||||||
// TODO You may want to include some logging here.
|
Log.e(TAG, ex.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* 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,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// based on from https://stackoverflow.com/a/45325876 (which did not work for me)
|
||||||
|
|
||||||
|
package com.m2049r.xmrwallet.layout;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.design.widget.TextInputLayout;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
public class CTextInputLayout extends TextInputLayout {
|
||||||
|
public CTextInputLayout(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CTextInputLayout(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBaseline() {
|
||||||
|
EditText editText = getEditText();
|
||||||
|
return editText.getBaseline() - (getMeasuredHeight() - editText.getMeasuredHeight());
|
||||||
|
}
|
||||||
|
}
|
399
app/src/main/java/com/m2049r/xmrwallet/layout/ExchangeView.java
Normal file
399
app/src/main/java/com/m2049r/xmrwallet/layout/ExchangeView.java
Normal file
File diff suppressed because it is too large
Load Diff
155
app/src/main/java/com/m2049r/xmrwallet/layout/Toolbar.java
Normal file
155
app/src/main/java/com/m2049r/xmrwallet/layout/Toolbar.java
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// based on https://code.tutsplus.com/tutorials/creating-compound-views-on-android--cms-22889
|
||||||
|
|
||||||
|
package com.m2049r.xmrwallet.layout;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.R;
|
||||||
|
|
||||||
|
public class Toolbar extends android.support.v7.widget.Toolbar {
|
||||||
|
static final String TAG = "Toolbar";
|
||||||
|
|
||||||
|
public interface OnButtonListener {
|
||||||
|
void onButton(int type);
|
||||||
|
}
|
||||||
|
|
||||||
|
OnButtonListener onButtonListener;
|
||||||
|
|
||||||
|
public void setOnButtonListener(OnButtonListener listener) {
|
||||||
|
onButtonListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageView toolbarImage;
|
||||||
|
TextView toolbarTitle;
|
||||||
|
TextView toolbarSubtitle;
|
||||||
|
Button bDonate;
|
||||||
|
|
||||||
|
public Toolbar(Context context) {
|
||||||
|
super(context);
|
||||||
|
initializeViews(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Toolbar(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
initializeViews(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Toolbar(Context context,
|
||||||
|
AttributeSet attrs,
|
||||||
|
int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
initializeViews(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inflates the views in the layout.
|
||||||
|
*
|
||||||
|
* @param context the current context for the view.
|
||||||
|
*/
|
||||||
|
private void initializeViews(Context context) {
|
||||||
|
LayoutInflater inflater = (LayoutInflater) context
|
||||||
|
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
inflater.inflate(R.layout.view_toolbar, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFinishInflate() {
|
||||||
|
super.onFinishInflate();
|
||||||
|
toolbarImage = (ImageView) findViewById(R.id.toolbarImage);
|
||||||
|
toolbarTitle = (TextView) findViewById(R.id.toolbarTitle);
|
||||||
|
toolbarSubtitle = (TextView) findViewById(R.id.toolbarSubtitle);
|
||||||
|
bDonate = (Button) findViewById(R.id.bDonate);
|
||||||
|
bDonate.setOnClickListener(new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (onButtonListener != null) {
|
||||||
|
onButtonListener.onButton(buttonType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title, String subtitle) {
|
||||||
|
setTitle(title);
|
||||||
|
setSubtitle(subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
toolbarTitle.setText(title);
|
||||||
|
if (title != null) {
|
||||||
|
toolbarImage.setVisibility(View.INVISIBLE);
|
||||||
|
toolbarTitle.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
toolbarImage.setVisibility(View.VISIBLE);
|
||||||
|
toolbarTitle.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static int BUTTON_NONE = 0;
|
||||||
|
public final static int BUTTON_BACK = 1;
|
||||||
|
public final static int BUTTON_CLOSE = 2;
|
||||||
|
public final static int BUTTON_DONATE = 3;
|
||||||
|
|
||||||
|
int buttonType = BUTTON_DONATE;
|
||||||
|
|
||||||
|
public void setButton(int type) {
|
||||||
|
switch (type) {
|
||||||
|
case BUTTON_BACK:
|
||||||
|
Log.d(TAG, "BUTTON_BACK");
|
||||||
|
bDonate.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_arrow_back_white_24dp, 0, 0, 0);
|
||||||
|
bDonate.setText(null);
|
||||||
|
bDonate.setVisibility(View.VISIBLE);
|
||||||
|
break;
|
||||||
|
case BUTTON_CLOSE:
|
||||||
|
Log.d(TAG, "BUTTON_CLOSE");
|
||||||
|
bDonate.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_close_white_24dp, 0, 0, 0);
|
||||||
|
bDonate.setText(R.string.label_close);
|
||||||
|
bDonate.setVisibility(View.VISIBLE);
|
||||||
|
break;
|
||||||
|
case BUTTON_DONATE:
|
||||||
|
Log.d(TAG, "BUTTON_DONATE");
|
||||||
|
bDonate.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_favorite_white_24dp, 0, 0, 0);
|
||||||
|
bDonate.setText(R.string.label_donate);
|
||||||
|
bDonate.setVisibility(View.VISIBLE);
|
||||||
|
break;
|
||||||
|
case BUTTON_NONE:
|
||||||
|
default:
|
||||||
|
Log.d(TAG, "BUTTON_NONE");
|
||||||
|
bDonate.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||||
|
bDonate.setText(null);
|
||||||
|
bDonate.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
buttonType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubtitle(String subtitle) {
|
||||||
|
toolbarSubtitle.setText(subtitle);
|
||||||
|
if (subtitle != null) {
|
||||||
|
toolbarSubtitle.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
toolbarSubtitle.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -17,7 +17,6 @@
|
|||||||
package com.m2049r.xmrwallet.layout;
|
package com.m2049r.xmrwallet.layout;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
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.util.Log;
|
||||||
@@ -28,13 +27,12 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import com.m2049r.xmrwallet.R;
|
import com.m2049r.xmrwallet.R;
|
||||||
import com.m2049r.xmrwallet.model.TransactionInfo;
|
import com.m2049r.xmrwallet.model.TransactionInfo;
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
@@ -69,7 +67,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
outboundColour = ContextCompat.getColor(context, R.color.tx_red);
|
outboundColour = ContextCompat.getColor(context, R.color.tx_red);
|
||||||
pendingColour = ContextCompat.getColor(context, R.color.tx_pending);
|
pendingColour = ContextCompat.getColor(context, R.color.tx_pending);
|
||||||
failedColour = ContextCompat.getColor(context, R.color.tx_failed);
|
failedColour = ContextCompat.getColor(context, R.color.tx_failed);
|
||||||
this.infoItems = new ArrayList<>();
|
infoItems = new ArrayList<>();
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
TimeZone tz = cal.getTimeZone(); //get the local time zone.
|
TimeZone tz = cal.getTimeZone(); //get the local time zone.
|
||||||
@@ -79,7 +77,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(parent.getContext())
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
.inflate(R.layout.transaction_item, parent, false);
|
.inflate(R.layout.item_transaction, parent, false);
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,22 +97,8 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
this.infoItems.clear();
|
this.infoItems.clear();
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
Log.d(TAG, "setInfos " + data.size());
|
Log.d(TAG, "setInfos " + data.size());
|
||||||
// sort by block height
|
infoItems.addAll(data);
|
||||||
Collections.sort(data, new Comparator<TransactionInfo>() {
|
Collections.sort(infoItems);
|
||||||
@Override
|
|
||||||
public int compare(TransactionInfo o1, TransactionInfo o2) {
|
|
||||||
long b1 = o1.timestamp;
|
|
||||||
long b2 = o2.timestamp;
|
|
||||||
if (b1 > b2) {
|
|
||||||
return -1;
|
|
||||||
} else if (b1 < b2) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return o1.hash.compareTo(o2.hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.infoItems.addAll(data);
|
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "setInfos null");
|
Log.d(TAG, "setInfos null");
|
||||||
}
|
}
|
||||||
@@ -147,36 +131,41 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||||||
|
|
||||||
void bind(int position) {
|
void bind(int position) {
|
||||||
this.infoItem = infoItems.get(position);
|
this.infoItem = infoItems.get(position);
|
||||||
String displayAmount = Wallet.getDisplayAmount(infoItem.amount);
|
|
||||||
// TODO fix this with i8n code but cryptonote::print_money always uses '.' for decimal point
|
long realAmount = infoItem.amount;
|
||||||
String amount = displayAmount.substring(0, displayAmount.length() - (12 - 5));
|
if (infoItem.isPending) {
|
||||||
this.tvAmount.setText(amount);
|
realAmount = realAmount - infoItem.fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
String displayAmount = Helper.getDisplayAmount(realAmount, Helper.DISPLAY_DIGITS_INFO);
|
||||||
|
if (infoItem.direction == TransactionInfo.Direction.Direction_Out) {
|
||||||
|
this.tvAmount.setText(context.getString(R.string.tx_list_amount_negative, displayAmount));
|
||||||
|
} else {
|
||||||
|
this.tvAmount.setText(context.getString(R.string.tx_list_amount_positive, displayAmount));
|
||||||
|
}
|
||||||
|
|
||||||
if ((infoItem.fee > 0)) {
|
if ((infoItem.fee > 0)) {
|
||||||
String feeAmount = Wallet.getDisplayAmount(infoItem.fee);
|
String fee = Helper.getDisplayAmount(infoItem.fee, 5);
|
||||||
String fee = feeAmount.substring(0, feeAmount.length() - (12 - 5));
|
|
||||||
if (infoItem.isPending) {
|
|
||||||
this.tvFee.setText(context.getString(R.string.tx_list_fee_pending, fee));
|
|
||||||
} else {
|
|
||||||
this.tvFee.setText(context.getString(R.string.tx_list_fee, fee));
|
this.tvFee.setText(context.getString(R.string.tx_list_fee, fee));
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.tvFee.setText("");
|
this.tvFee.setText("");
|
||||||
}
|
}
|
||||||
if (infoItem.isFailed) {
|
if (infoItem.isFailed) {
|
||||||
this.tvAmount.setText(context.getString(R.string.tx_list_amount_failed, amount));
|
this.tvAmount.setText(context.getString(R.string.tx_list_amount_failed, displayAmount));
|
||||||
|
this.tvFee.setText(context.getString(R.string.tx_list_failed_text));
|
||||||
setTxColour(failedColour);
|
setTxColour(failedColour);
|
||||||
} else if (infoItem.isPending) {
|
} else if (infoItem.isPending) {
|
||||||
setTxColour(pendingColour);
|
setTxColour(pendingColour);
|
||||||
if (infoItem.direction == TransactionInfo.Direction.Direction_Out) {
|
|
||||||
this.tvAmount.setText(context.getString(R.string.tx_list_amount_negative, amount));
|
|
||||||
}
|
|
||||||
} else if (infoItem.direction == TransactionInfo.Direction.Direction_In) {
|
} else if (infoItem.direction == TransactionInfo.Direction.Direction_In) {
|
||||||
setTxColour(inboundColour);
|
setTxColour(inboundColour);
|
||||||
} else {
|
} else {
|
||||||
setTxColour(outboundColour);
|
setTxColour(outboundColour);
|
||||||
}
|
}
|
||||||
|
if ((infoItem.notes == null) || (infoItem.notes.isEmpty())) {
|
||||||
this.tvPaymentId.setText(infoItem.paymentId.equals("0000000000000000") ? "" : infoItem.paymentId);
|
this.tvPaymentId.setText(infoItem.paymentId.equals("0000000000000000") ? "" : infoItem.paymentId);
|
||||||
|
} else {
|
||||||
|
this.tvPaymentId.setText(infoItem.notes);
|
||||||
|
}
|
||||||
this.tvDateTime.setText(getDateTime(infoItem.timestamp));
|
this.tvDateTime.setText(getDateTime(infoItem.timestamp));
|
||||||
|
|
||||||
itemView.setOnClickListener(this);
|
itemView.setOnClickListener(this);
|
||||||
|
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* 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.v7.widget.PopupMenu;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.R;
|
||||||
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
public interface OnInteractionListener {
|
||||||
|
void onInteraction(View view, WalletManager.WalletInfo item);
|
||||||
|
|
||||||
|
boolean onContextInteraction(MenuItem item, WalletManager.WalletInfo infoItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<WalletManager.WalletInfo> infoItems;
|
||||||
|
private final OnInteractionListener listener;
|
||||||
|
|
||||||
|
Context context;
|
||||||
|
|
||||||
|
public WalletInfoAdapter(Context context, OnInteractionListener listener) {
|
||||||
|
this.context = context;
|
||||||
|
this.infoItems = new ArrayList<>();
|
||||||
|
this.listener = listener;
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
TimeZone tz = cal.getTimeZone(); //get the local time zone.
|
||||||
|
DATETIME_FORMATTER.setTimeZone(tz);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.item_wallet, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(final ViewHolder holder, int position) {
|
||||||
|
holder.bind(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return infoItems.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WalletManager.WalletInfo getItem(int position) {
|
||||||
|
return infoItems.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInfos(List<WalletManager.WalletInfo> data) {
|
||||||
|
// TODO do stuff with data so we can really recycle elements (i.e. add only new tx)
|
||||||
|
// as the WalletInfo items are always recreated, we cannot recycle
|
||||||
|
infoItems.clear();
|
||||||
|
if (data != null) {
|
||||||
|
Log.d(TAG, "setInfos " + data.size());
|
||||||
|
infoItems.addAll(data);
|
||||||
|
Collections.sort(infoItems);
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "setInfos null");
|
||||||
|
}
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
|
final TextView tvName;
|
||||||
|
final TextView tvAddress;
|
||||||
|
final ImageButton ibOptions;
|
||||||
|
WalletManager.WalletInfo infoItem;
|
||||||
|
|
||||||
|
ViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
tvName = (TextView) itemView.findViewById(R.id.tvName);
|
||||||
|
tvAddress = (TextView) itemView.findViewById(R.id.tvAddress);
|
||||||
|
ibOptions = (ImageButton) itemView.findViewById(R.id.ibOptions);
|
||||||
|
ibOptions.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
//creating a popup menu
|
||||||
|
PopupMenu popup = new PopupMenu(context, ibOptions);
|
||||||
|
//inflating menu from xml resource
|
||||||
|
popup.inflate(R.menu.list_context_menu);
|
||||||
|
//adding click listener
|
||||||
|
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
|
if (listener != null) {
|
||||||
|
return listener.onContextInteraction(item, infoItem);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//displaying the popup
|
||||||
|
popup.show();
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
itemView.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDateTime(long time) {
|
||||||
|
return DATETIME_FORMATTER.format(new Date(time * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind(int position) {
|
||||||
|
infoItem = infoItems.get(position);
|
||||||
|
tvName.setText(infoItem.name);
|
||||||
|
tvAddress.setText(infoItem.address.substring(0, 16) + "...");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
if (listener != null) {
|
||||||
|
int position = getAdapterPosition(); // gets item position
|
||||||
|
if (position != RecyclerView.NO_POSITION) { // Check if an item was deleted, but the user clicked it before the UI removed it
|
||||||
|
listener.onInteraction(view, infoItems.get(position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -30,6 +30,12 @@ public class TransactionHistory {
|
|||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadNotes(Wallet wallet) {
|
||||||
|
for (TransactionInfo info : transactions) {
|
||||||
|
info.notes = wallet.getUserNote(info.hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public native int getCount();
|
public native int getCount();
|
||||||
|
|
||||||
//private native long getTransactionByIndexJ(int i);
|
//private native long getTransactionByIndexJ(int i);
|
||||||
@@ -42,6 +48,11 @@ public class TransactionHistory {
|
|||||||
|
|
||||||
private List<TransactionInfo> transactions = new ArrayList<>();
|
private List<TransactionInfo> transactions = new ArrayList<>();
|
||||||
|
|
||||||
|
public void refreshWithNotes(Wallet wallet) {
|
||||||
|
refresh();
|
||||||
|
loadNotes(wallet);
|
||||||
|
}
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
transactions = refreshJ();
|
transactions = refreshJ();
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@ import java.util.Random;
|
|||||||
|
|
||||||
// this is not the TransactionInfo from the API as that is owned by the TransactionHistory
|
// this is not the TransactionInfo from the API as that is owned by the TransactionHistory
|
||||||
// this is a POJO for the TransactionInfoAdapter
|
// this is a POJO for the TransactionInfoAdapter
|
||||||
public class TransactionInfo implements Parcelable {
|
public class TransactionInfo implements Parcelable, Comparable<TransactionInfo> {
|
||||||
static final String TAG = "TransactionInfo";
|
static final String TAG = "TransactionInfo";
|
||||||
|
|
||||||
public enum Direction {
|
public enum Direction {
|
||||||
@@ -92,7 +92,6 @@ public class TransactionInfo implements Parcelable {
|
|||||||
this.confirmations = confirmations;
|
this.confirmations = confirmations;
|
||||||
this.transfers = transfers;
|
this.transfers = transfers;
|
||||||
}
|
}
|
||||||
Random rnd = new Random();
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return direction + "@" + blockheight + " " + amount;
|
return direction + "@" + blockheight + " " + amount;
|
||||||
@@ -146,4 +145,17 @@ public class TransactionInfo implements Parcelable {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(TransactionInfo another) {
|
||||||
|
long b1 = this.timestamp;
|
||||||
|
long b2 = another.timestamp;
|
||||||
|
if (b1 > b2) {
|
||||||
|
return -1;
|
||||||
|
} else if (b1 < b2) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return this.hash.compareTo(another.hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user