1
mirror of https://github.com/m2049r/xmrwallet synced 2024-11-29 10:20:23 +01:00
This commit is contained in:
m2049r 2018-06-14 21:32:52 +02:00 committed by GitHub
parent 975cc4f43c
commit af0ecb2894
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 606 additions and 49 deletions

View File

@ -551,9 +551,10 @@ Java_com_m2049r_xmrwallet_model_Wallet_setPassword(JNIEnv *env, jobject instance
} }
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getAddressJ(JNIEnv *env, jobject instance) { Java_com_m2049r_xmrwallet_model_Wallet_getAddressJ(JNIEnv *env, jobject instance,
jint accountIndex) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance); Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
return env->NewStringUTF(wallet->address().c_str()); return env->NewStringUTF(wallet->address((uint32_t) accountIndex).c_str());
} }
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
@ -646,15 +647,29 @@ Java_com_m2049r_xmrwallet_model_Wallet_getConnectionStatusJ(JNIEnv *env, jobject
//TODO virtual bool trustedDaemon() const = 0; //TODO virtual bool trustedDaemon() const = 0;
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getBalance(JNIEnv *env, jobject instance) { Java_com_m2049r_xmrwallet_model_Wallet_getBalance(JNIEnv *env, jobject instance,
jint accountIndex) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance); Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
return wallet->balance(); return wallet->balance((uint32_t) accountIndex);
} }
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getUnlockedBalance(JNIEnv *env, jobject instance) { Java_com_m2049r_xmrwallet_model_Wallet_getBalanceAll(JNIEnv *env, jobject instance) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance); Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
return wallet->unlockedBalance(); return wallet->balanceAll();
}
JNIEXPORT jlong JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getUnlockedBalance(JNIEnv *env, jobject instance,
jint accountIndex) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
return wallet->unlockedBalance((uint32_t) accountIndex);
}
JNIEXPORT jlong JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getUnlockedBalanceAll(JNIEnv *env, jobject instance) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
return wallet->unlockedBalanceAll();
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
@ -814,7 +829,8 @@ JNIEXPORT jlong JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_createTransactionJ(JNIEnv *env, jobject instance, Java_com_m2049r_xmrwallet_model_Wallet_createTransactionJ(JNIEnv *env, jobject instance,
jstring dst_addr, jstring payment_id, jstring dst_addr, jstring payment_id,
jlong amount, jint mixin_count, jlong amount, jint mixin_count,
jint priority) { jint priority,
jint accountIndex) {
const char *_dst_addr = env->GetStringUTFChars(dst_addr, NULL); const char *_dst_addr = env->GetStringUTFChars(dst_addr, NULL);
const char *_payment_id = env->GetStringUTFChars(payment_id, NULL); const char *_payment_id = env->GetStringUTFChars(payment_id, NULL);
@ -823,8 +839,9 @@ Java_com_m2049r_xmrwallet_model_Wallet_createTransactionJ(JNIEnv *env, jobject i
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance); Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
Bitmonero::PendingTransaction *tx = wallet->createTransaction(_dst_addr, _payment_id, Bitmonero::PendingTransaction *tx = wallet->createTransaction(_dst_addr, _payment_id,
amount, mixin_count, amount, (uint32_t) mixin_count,
_priority); _priority,
(uint32_t) accountIndex);
env->ReleaseStringUTFChars(dst_addr, _dst_addr); env->ReleaseStringUTFChars(dst_addr, _dst_addr);
env->ReleaseStringUTFChars(payment_id, _payment_id); env->ReleaseStringUTFChars(payment_id, _payment_id);
@ -943,6 +960,54 @@ Java_com_m2049r_xmrwallet_model_Wallet_getTxKey(JNIEnv *env, jobject instance,
return env->NewStringUTF(txKey.c_str()); return env->NewStringUTF(txKey.c_str());
} }
//virtual void addSubaddressAccount(const std::string& label) = 0;
JNIEXPORT void JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_addAccount(JNIEnv *env, jobject instance,
jstring label) {
const char *_label = env->GetStringUTFChars(label, NULL);
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
wallet->addSubaddressAccount(_label);
env->ReleaseStringUTFChars(label, _label);
}
//virtual std::string getSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex) const = 0;
JNIEXPORT jstring JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_getSubaddressLabel(JNIEnv *env, jobject instance,
jint accountIndex, jint addressIndex) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
std::string label = wallet->getSubaddressLabel((uint32_t) accountIndex,
(uint32_t) addressIndex);
return env->NewStringUTF(label.c_str());
}
//virtual void setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label) = 0;
JNIEXPORT void JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_setSubaddressLabel(JNIEnv *env, jobject instance,
jint accountIndex, jint addressIndex,
jstring label) {
const char *_label = env->GetStringUTFChars(label, NULL);
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
wallet->setSubaddressLabel(accountIndex, addressIndex, _label);
env->ReleaseStringUTFChars(label, _label);
}
// virtual size_t numSubaddressAccounts() const = 0;
JNIEXPORT jint JNICALL
Java_com_m2049r_xmrwallet_model_Wallet_numSubaddressAccounts(JNIEnv *env, jobject instance) {
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
return wallet->numSubaddressAccounts();
}
//virtual std::string signMessage(const std::string &message) = 0; //virtual std::string signMessage(const std::string &message) = 0;
//virtual bool verifySignedMessage(const std::string &message, const std::string &addres, const std::string &signature) const = 0; //virtual bool verifySignedMessage(const std::string &message, const std::string &addres, const std::string &signature) const = 0;
@ -989,7 +1054,7 @@ jobject newTransferList(JNIEnv *env, Bitmonero::TransactionInfo *info) {
jobject newTransactionInfo(JNIEnv *env, Bitmonero::TransactionInfo *info) { jobject newTransactionInfo(JNIEnv *env, Bitmonero::TransactionInfo *info) {
jmethodID c = env->GetMethodID(class_TransactionInfo, "<init>", jmethodID c = env->GetMethodID(class_TransactionInfo, "<init>",
"(IZZJJJLjava/lang/String;JLjava/lang/String;JLjava/util/List;)V"); "(IZZJJJLjava/lang/String;JLjava/lang/String;IJLjava/util/List;)V");
jobject transfers = newTransferList(env, info); jobject transfers = newTransferList(env, info);
jstring _hash = env->NewStringUTF(info->hash().c_str()); jstring _hash = env->NewStringUTF(info->hash().c_str());
jstring _paymentId = env->NewStringUTF(info->paymentId().c_str()); jstring _paymentId = env->NewStringUTF(info->paymentId().c_str());
@ -1003,6 +1068,7 @@ jobject newTransactionInfo(JNIEnv *env, Bitmonero::TransactionInfo *info) {
_hash, _hash,
static_cast<jlong> (info->timestamp()), static_cast<jlong> (info->timestamp()),
_paymentId, _paymentId,
info->subaddrAccount(),
info->confirmations(), info->confirmations(),
transfers); transfers);
env->DeleteLocalRef(transfers); env->DeleteLocalRef(transfers);
@ -1178,7 +1244,6 @@ Java_com_m2049r_xmrwallet_model_WalletManager_setLogLevel(JNIEnv *env, jobject i
Bitmonero::WalletManagerFactory::setLogLevel(level); Bitmonero::WalletManagerFactory::setLogLevel(level);
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -59,6 +59,7 @@ public class TxFragment extends Fragment {
TS_FORMATTER.setTimeZone(tz); TS_FORMATTER.setTimeZone(tz);
} }
private TextView tvAccount;
private TextView tvTxTimestamp; private TextView tvTxTimestamp;
private TextView tvTxId; private TextView tvTxId;
private TextView tvTxKey; private TextView tvTxKey;
@ -88,6 +89,7 @@ public class TxFragment extends Fragment {
tvDestinationBtc = (TextView) view.findViewById(R.id.tvDestinationBtc); tvDestinationBtc = (TextView) view.findViewById(R.id.tvDestinationBtc);
tvTxAmountBtc = (TextView) view.findViewById(R.id.tvTxAmountBtc); tvTxAmountBtc = (TextView) view.findViewById(R.id.tvTxAmountBtc);
tvAccount = (TextView) view.findViewById(R.id.tvAccount);
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);
tvTxKey = (TextView) view.findViewById(R.id.tvTxKey); tvTxKey = (TextView) view.findViewById(R.id.tvTxKey);
@ -222,6 +224,8 @@ public class TxFragment extends Fragment {
activityCallback.setSubtitle(getString(R.string.tx_title)); activityCallback.setSubtitle(getString(R.string.tx_title));
activityCallback.setToolbarButton(Toolbar.BUTTON_BACK); activityCallback.setToolbarButton(Toolbar.BUTTON_BACK);
tvAccount.setText("" + info.subaddrAccount);
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);

View File

@ -28,10 +28,21 @@ import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.PowerManager; import android.os.PowerManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
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.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.m2049r.xmrwallet.data.BarcodeData; import com.m2049r.xmrwallet.data.BarcodeData;
@ -49,6 +60,9 @@ import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.UserNotes; import com.m2049r.xmrwallet.util.UserNotes;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
import java.util.ArrayList;
import java.util.List;
import timber.log.Timber; import timber.log.Timber;
public class WalletActivity extends SecureActivity implements WalletFragment.Listener, public class WalletActivity extends SecureActivity implements WalletFragment.Listener,
@ -57,12 +71,18 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
GenerateReviewFragment.Listener, GenerateReviewFragment.Listener,
GenerateReviewFragment.PasswordChangedListener, GenerateReviewFragment.PasswordChangedListener,
ScannerFragment.OnScannedListener, ReceiveFragment.Listener, ScannerFragment.OnScannedListener, ReceiveFragment.Listener,
SendAddressWizardFragment.OnScanListener { SendAddressWizardFragment.OnScanListener,
WalletFragment.DrawerLocker,
NavigationView.OnNavigationItemSelectedListener {
public static final String REQUEST_ID = "id"; public static final String REQUEST_ID = "id";
public static final String REQUEST_PW = "pw"; public static final String REQUEST_PW = "pw";
public static final String REQUEST_FINGERPRINT_USED = "fingerprint"; public static final String REQUEST_FINGERPRINT_USED = "fingerprint";
private NavigationView accountsView;
private DrawerLayout drawer;
private ActionBarDrawerToggle drawerToggle;
private Toolbar toolbar; private Toolbar toolbar;
private boolean needVerifyIdentity; private boolean needVerifyIdentity;
@ -155,10 +175,11 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
@Override @Override
protected void onDestroy() { protected void onDestroy() {
Timber.d("onDestroy()"); Timber.d("onDestroy()");
if ((mBoundService != null) && !isSynced() && (getWallet() != null)) { if ((mBoundService != null) && (getWallet() != null)) {
saveWallet(); saveWallet();
} }
stopWalletService(); stopWalletService();
drawer.removeDrawerListener(drawerToggle);
super.onDestroy(); super.onDestroy();
} }
@ -167,6 +188,14 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
return haveWallet; return haveWallet;
} }
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem renameItem = menu.findItem(R.id.action_rename);
if (renameItem != null)
renameItem.setVisible(hasWallet() && getWallet().isSynchronized());
return true;
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
@ -194,6 +223,9 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
case R.id.action_help_send: case R.id.action_help_send:
HelpFragment.display(getSupportFragmentManager(), R.string.help_send); HelpFragment.display(getSupportFragmentManager(), R.string.help_send);
return true; return true;
case R.id.action_rename:
onAccountRename();
return true;
default: default:
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@ -253,6 +285,16 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
} }
}); });
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar,
R.string.accounts_drawer_open, R.string.accounts_drawer_close);
drawer.addDrawerListener(drawerToggle);
drawerToggle.syncState();
setDrawerEnabled(false); // disable until synced
accountsView = (NavigationView) findViewById(R.id.accounts_nav);
accountsView.setNavigationItemSelectedListener(this);
showNet(); showNet();
Fragment walletFragment = new WalletFragment(); Fragment walletFragment = new WalletFragment();
@ -280,7 +322,6 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
} }
} }
public Wallet getWallet() { public Wallet getWallet() {
if (mBoundService == null) throw new IllegalStateException("WalletService not bound."); if (mBoundService == null) throw new IllegalStateException("WalletService not bound.");
return mBoundService.getWallet(); return mBoundService.getWallet();
@ -444,10 +485,20 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
// WalletService.Observer // WalletService.Observer
/////////////////////////// ///////////////////////////
private int numAccounts = -1;
// refresh and return true if successful // refresh and return true if successful
@Override @Override
public boolean onRefreshed(final Wallet wallet, final boolean full) { public boolean onRefreshed(final Wallet wallet, final boolean full) {
Timber.d("onRefreshed()"); Timber.d("onRefreshed()");
if (numAccounts != wallet.numAccounts()) {
numAccounts = wallet.numAccounts();
runOnUiThread(new Runnable() {
public void run() {
updateAccountsList();
}
});
}
try { try {
final WalletFragment walletFragment = (WalletFragment) final WalletFragment walletFragment = (WalletFragment)
getSupportFragmentManager().findFragmentByTag(WalletFragment.class.getName()); getSupportFragmentManager().findFragmentByTag(WalletFragment.class.getName());
@ -869,6 +920,11 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
@Override @Override
public void onBackPressed() { public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
return;
}
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container); final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (fragment instanceof OnBackPressedListener) { if (fragment instanceof OnBackPressedListener) {
if (!((OnBackPressedListener) fragment).onBackPressed()) { if (!((OnBackPressedListener) fragment).onBackPressed()) {
@ -889,4 +945,128 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
return getPreferences(Context.MODE_PRIVATE); return getPreferences(Context.MODE_PRIVATE);
} }
private List<Integer> accountIds = new ArrayList<>();
// generate and cache unique ids for use in accounts list
private int getAccountId(int accountIndex) {
final int n = accountIds.size();
for (int i = n; i <= accountIndex; i++) {
accountIds.add(View.generateViewId());
}
return accountIds.get(accountIndex);
}
// drawer stuff
void updateAccountsList() {
final Wallet wallet = getWallet();
final TextView tvName = (TextView) accountsView.getHeaderView(0).findViewById(R.id.tvName);
tvName.setText(wallet.getName());
final TextView tvBalance = (TextView) accountsView.getHeaderView(0).findViewById(R.id.tvBalance);
tvBalance.setText(getString(R.string.accounts_balance,
Helper.getDisplayAmount(wallet.getBalanceAll() + wallet.getUnlockedBalanceAll(),
5)));
Menu menu = accountsView.getMenu();
menu.removeGroup(R.id.accounts_list);
for (int i = 0; i < wallet.numAccounts(); i++) {
final String label = wallet.getAccountLabel(i);
final MenuItem item = menu.add(R.id.accounts_list, getAccountId(i), 2 * i, label);
item.setIcon(R.drawable.ic_account_balance_wallet_black_24dp);
if (i == wallet.getAccountIndex())
item.setChecked(true);
}
menu.setGroupCheckable(R.id.accounts_list, true, true);
}
@Override
public void setDrawerEnabled(boolean enabled) {
Timber.d("setDrawerEnabled %b", enabled);
final int lockMode = enabled ? DrawerLayout.LOCK_MODE_UNLOCKED :
DrawerLayout.LOCK_MODE_LOCKED_CLOSED;
drawer.setDrawerLockMode(lockMode);
drawerToggle.setDrawerIndicatorEnabled(enabled);
invalidateOptionsMenu(); // menu may need to be changed
}
void updateAccountName() {
setSubtitle(getWallet().getAccountLabel());
updateAccountsList();
}
public void onAccountRename() {
final LayoutInflater li = LayoutInflater.from(this);
final View promptsView = li.inflate(R.layout.prompt_rename, null);
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setView(promptsView);
final EditText etRename = (EditText) promptsView.findViewById(R.id.etRename);
final TextView tvRenameLabel = (TextView) promptsView.findViewById(R.id.tvRenameLabel);
final Wallet wallet = getWallet();
tvRenameLabel.setText(getString(R.string.prompt_rename, wallet.getAccountLabel()));
// set dialog message
alertDialogBuilder
.setCancelable(false)
.setPositiveButton(getString(R.string.label_ok),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Helper.hideKeyboardAlways(WalletActivity.this);
String newName = etRename.getText().toString();
wallet.setAccountLabel(newName);
updateAccountName();
}
})
.setNegativeButton(getString(R.string.label_cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Helper.hideKeyboardAlways(WalletActivity.this);
dialog.cancel();
}
});
final AlertDialog dialog = alertDialogBuilder.create();
Helper.showKeyboard(dialog);
// accept keyboard "ok"
etRename.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)) {
Helper.hideKeyboardAlways(WalletActivity.this);
String newName = etRename.getText().toString();
dialog.cancel();
wallet.setAccountLabel(newName);
updateAccountName();
return false;
}
return false;
}
});
dialog.show();
}
@Override
public boolean onNavigationItemSelected(MenuItem item) {
final int id = item.getItemId();
switch (id) {
case R.id.account_new:
getWallet().addAccount();
int newIdx = getWallet().numAccounts() - 1;
getWallet().setAccountIndex(newIdx);
Toast.makeText(this,
getString(R.string.accounts_new, newIdx),
Toast.LENGTH_SHORT).show();
break;
default:
Timber.d("NavigationDrawer ID=%d", id);
int accountIdx = accountIds.indexOf(id);
if (accountIdx >= 0) {
Timber.d("found @%d", accountIdx);
getWallet().setAccountIndex(accountIdx);
}
}
forceUpdate();
drawer.closeDrawer(GravityCompat.START);
return true;
}
} }

View File

@ -257,7 +257,7 @@ public class WalletFragment extends Fragment
// called from activity // called from activity
public void onRefreshed(final Wallet wallet, final boolean full) { public void onRefreshed(final Wallet wallet, final boolean full) {
Timber.d("onRefreshed()"); Timber.d("onRefreshed(%b)", full);
if (full) { if (full) {
List<TransactionInfo> list = wallet.getHistory().getAll(); List<TransactionInfo> list = wallet.getHistory().getAll();
adapter.setInfos(list); adapter.setInfos(list);
@ -271,6 +271,7 @@ public class WalletFragment extends Fragment
bSend.setVisibility(View.VISIBLE); bSend.setVisibility(View.VISIBLE);
bSend.setEnabled(true); bSend.setEnabled(true);
} }
enableAccountsList(true);
} }
boolean walletLoaded = false; boolean walletLoaded = false;
@ -314,7 +315,7 @@ public class WalletFragment extends Fragment
if (wallet == null) return; if (wallet == null) return;
walletTitle = wallet.getName(); walletTitle = wallet.getName();
String watchOnly = (wallet.isWatchOnly() ? getString(R.string.label_watchonly) : ""); String watchOnly = (wallet.isWatchOnly() ? getString(R.string.label_watchonly) : "");
walletSubtitle = wallet.getAddress().substring(0, 10) + "" + watchOnly; walletSubtitle = wallet.getAccountLabel();
activityCallback.setTitle(walletTitle, walletSubtitle); activityCallback.setTitle(walletTitle, walletSubtitle);
Timber.d("wallet title is %s", walletTitle); Timber.d("wallet title is %s", walletTitle);
} }
@ -324,10 +325,13 @@ public class WalletFragment extends Fragment
private String walletSubtitle = null; private String walletSubtitle = null;
private long unlockedBalance = 0; private long unlockedBalance = 0;
private int accountIdx = -1;
private void updateStatus(Wallet wallet) { private void updateStatus(Wallet wallet) {
if (!isAdded()) return; if (!isAdded()) return;
Timber.d("updateStatus()"); Timber.d("updateStatus()");
if (walletTitle == null) { if ((walletTitle == null) || (accountIdx != wallet.getAccountIndex())) {
accountIdx = wallet.getAccountIndex();
setActivityTitle(wallet); setActivityTitle(wallet);
} }
long balance = wallet.getBalance(); long balance = wallet.getBalance();
@ -413,9 +417,27 @@ public class WalletFragment extends Fragment
super.onResume(); super.onResume();
Timber.d("onResume()"); Timber.d("onResume()");
activityCallback.setTitle(walletTitle, walletSubtitle); activityCallback.setTitle(walletTitle, walletSubtitle);
activityCallback.setToolbarButton(Toolbar.BUTTON_CLOSE); //activityCallback.setToolbarButton(Toolbar.BUTTON_CLOSE); // TODO: Close button somewhere else
activityCallback.setToolbarButton(Toolbar.BUTTON_NONE);
setProgress(syncProgress); setProgress(syncProgress);
setProgress(syncText); setProgress(syncText);
showReceive(); showReceive();
} }
@Override
public void onPause() {
enableAccountsList(false);
super.onPause();
}
public interface DrawerLocker {
void setDrawerEnabled(boolean enabled);
}
private void enableAccountsList(boolean enable) {
if (activityCallback instanceof DrawerLocker) {
((DrawerLocker) activityCallback).setDrawerEnabled(enable);
}
}
} }

View File

@ -17,8 +17,11 @@
package com.m2049r.xmrwallet.model; package com.m2049r.xmrwallet.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import timber.log.Timber;
public class TransactionHistory { public class TransactionHistory {
static { static {
System.loadLibrary("monerujo"); System.loadLibrary("monerujo");
@ -26,8 +29,18 @@ public class TransactionHistory {
private long handle; private long handle;
public TransactionHistory(long handle) { int accountIndex;
public void setAccountFor(Wallet wallet) {
if (accountIndex != wallet.getAccountIndex()) {
this.accountIndex = wallet.getAccountIndex();
refreshWithNotes(wallet);
}
}
public TransactionHistory(long handle, int accountIndex) {
this.handle = handle; this.handle = handle;
this.accountIndex = accountIndex;
} }
public void loadNotes(Wallet wallet) { public void loadNotes(Wallet wallet) {
@ -36,7 +49,7 @@ public class TransactionHistory {
} }
} }
public native int getCount(); public native int getCount(); // over all accounts/subaddresses
//private native long getTransactionByIndexJ(int i); //private native long getTransactionByIndexJ(int i);
@ -53,8 +66,23 @@ public class TransactionHistory {
loadNotes(wallet); loadNotes(wallet);
} }
// public void refresh() {
// transactions = refreshJ();
// }
public void refresh() { public void refresh() {
transactions = refreshJ(); List<TransactionInfo> t = refreshJ();
Timber.d("refreshed %d", t.size());
for (Iterator<TransactionInfo> iterator = t.iterator(); iterator.hasNext(); ) {
TransactionInfo info = iterator.next();
if (info.subaddrAccount != accountIndex) {
iterator.remove();
Timber.d("removed %s", info.hash);
} else {
Timber.d("kept %s", info.hash);
}
}
transactions = t;
} }
private native List<TransactionInfo> refreshJ(); private native List<TransactionInfo> refreshJ();

View File

@ -53,6 +53,11 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
} }
} }
// virtual std::set<uint32_t> subaddrIndex() const = 0;
// virtual uint32_t subaddrAccount() const = 0;
// virtual std::string label() const = 0;
// virtual uint64_t confirmations() const = 0;
public Direction direction; public Direction direction;
public boolean isPending; public boolean isPending;
public boolean isFailed; public boolean isFailed;
@ -62,6 +67,7 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
public String hash; public String hash;
public long timestamp; public long timestamp;
public String paymentId; public String paymentId;
public int subaddrAccount;
public long confirmations; public long confirmations;
public List<Transfer> transfers; public List<Transfer> transfers;
@ -78,6 +84,7 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
String hash, String hash,
long timestamp, long timestamp,
String paymentId, String paymentId,
int subaddrAccount,
long confirmations, long confirmations,
List<Transfer> transfers) { List<Transfer> transfers) {
this.direction = Direction.values()[direction]; this.direction = Direction.values()[direction];
@ -89,6 +96,7 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
this.hash = hash; this.hash = hash;
this.timestamp = timestamp; this.timestamp = timestamp;
this.paymentId = paymentId; this.paymentId = paymentId;
this.subaddrAccount = subaddrAccount;
this.confirmations = confirmations; this.confirmations = confirmations;
this.transfers = transfers; this.transfers = transfers;
} }
@ -108,6 +116,7 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
out.writeString(hash); out.writeString(hash);
out.writeLong(timestamp); out.writeLong(timestamp);
out.writeString(paymentId); out.writeString(paymentId);
out.writeInt(subaddrAccount);
out.writeLong(confirmations); out.writeLong(confirmations);
out.writeList(transfers); out.writeList(transfers);
out.writeString(txKey); out.writeString(txKey);
@ -134,6 +143,7 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
hash = in.readString(); hash = in.readString();
timestamp = in.readLong(); timestamp = in.readLong();
paymentId = in.readString(); paymentId = in.readString();
subaddrAccount = in.readInt();
confirmations = in.readLong(); confirmations = in.readLong();
transfers = in.readArrayList(Transfer.class.getClassLoader()); transfers = in.readArrayList(Transfer.class.getClassLoader());
txKey = in.readString(); txKey = in.readString();

View File

@ -20,12 +20,24 @@ import com.m2049r.xmrwallet.data.TxData;
import java.io.File; import java.io.File;
import timber.log.Timber;
public class Wallet { public class Wallet {
static { static {
System.loadLibrary("monerujo"); System.loadLibrary("monerujo");
} }
static final String TAG = "Wallet"; private int accountIndex = 0;
public int getAccountIndex() {
return accountIndex;
}
public void setAccountIndex(int accountIndex) {
Timber.d("setAccountIndex(%d)", accountIndex);
this.accountIndex = accountIndex;
getHistory().setAccountFor(this);
}
public String getName() { public String getName() {
return new File(getPath()).getName(); return new File(getPath()).getName();
@ -38,6 +50,11 @@ public class Wallet {
this.handle = handle; this.handle = handle;
} }
Wallet(long handle, int accountIndex) {
this.handle = handle;
this.accountIndex = accountIndex;
}
public enum Status { public enum Status {
Status_Ok, Status_Ok,
Status_Error, Status_Error,
@ -66,16 +83,11 @@ public class Wallet {
public native boolean setPassword(String password); public native boolean setPassword(String password);
private String address = null;
public String getAddress() { public String getAddress() {
if (address == null) { return getAddressJ(accountIndex);
address = getAddressJ();
}
return address;
} }
private native String getAddressJ(); private native String getAddressJ(int accountIndex);
public native String getPath(); public native String getPath();
@ -132,9 +144,21 @@ public class Wallet {
//TODO virtual void setTrustedDaemon(bool arg) = 0; //TODO virtual void setTrustedDaemon(bool arg) = 0;
//TODO virtual bool trustedDaemon() const = 0; //TODO virtual bool trustedDaemon() const = 0;
public native long getBalance(); public long getBalance() {
return getBalance(accountIndex);
}
public native long getUnlockedBalance(); public native long getBalance(int accountIndex);
public native long getBalanceAll();
public long getUnlockedBalance() {
return getUnlockedBalance(accountIndex);
}
public native long getUnlockedBalanceAll();
public native long getUnlockedBalance(int accountIndex);
public native boolean isWatchOnly(); public native boolean isWatchOnly();
@ -207,14 +231,15 @@ public class Wallet {
PendingTransaction.Priority priority) { PendingTransaction.Priority priority) {
disposePendingTransaction(); disposePendingTransaction();
int _priority = priority.getValue(); int _priority = priority.getValue();
long txHandle = createTransactionJ(dst_addr, payment_id, amount, mixin_count, _priority); long txHandle = createTransactionJ(dst_addr, payment_id, amount, mixin_count, _priority,
accountIndex);
pendingTransaction = new PendingTransaction(txHandle); pendingTransaction = new PendingTransaction(txHandle);
return pendingTransaction; return pendingTransaction;
} }
private native long createTransactionJ(String dst_addr, String payment_id, private native long createTransactionJ(String dst_addr, String payment_id,
long amount, int mixin_count, long amount, int mixin_count,
int priority); int priority, int accountIndex);
public PendingTransaction createSweepUnmixableTransaction() { public PendingTransaction createSweepUnmixableTransaction() {
@ -241,7 +266,7 @@ public class Wallet {
public TransactionHistory getHistory() { public TransactionHistory getHistory() {
if (history == null) { if (history == null) {
history = new TransactionHistory(getHistoryJ()); history = new TransactionHistory(getHistoryJ(), accountIndex);
} }
return history; return history;
} }
@ -273,4 +298,43 @@ public class Wallet {
//virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &tvAmount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) = 0; //virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &tvAmount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) = 0;
//virtual bool rescanSpent() = 0; //virtual bool rescanSpent() = 0;
private static final String NEW_ACCOUNT_NAME = "Untitled account"; // src/wallet/wallet2.cpp:941
public void addAccount() {
addAccount(NEW_ACCOUNT_NAME);
}
public native void addAccount(String label);
public String getAccountLabel() {
return getAccountLabel(accountIndex);
}
public String getAccountLabel(int accountIndex) {
String label = getSubaddressLabel(accountIndex, 0);
if (label.equals(NEW_ACCOUNT_NAME)) {
String address = getAddressJ(accountIndex);
int len = address.length();
return address.substring(0, 6) +
"\u2026" + address.substring(len - 6, len);
} else return label;
}
public native String getSubaddressLabel(int accountIndex, int addressIndex);
public void setAccountLabel(String label) {
setSubaddressLabel(accountIndex, 0, label);
}
public void setAccountLabel(int accountIndex, String label) {
setSubaddressLabel(accountIndex, 0, label);
}
public native void setSubaddressLabel(int accountIndex, int addressIndex, String label);
public int numAccounts() {
return numSubaddressAccounts();
}
public native int numSubaddressAccounts();
} }

View File

@ -80,6 +80,13 @@ public class WalletManager {
private native long createWalletJ(String path, String password, String language, int networkType); private native long createWalletJ(String path, String password, String language, int networkType);
public Wallet openAccount(String path, int accountIndex, String password) {
long walletHandle = openWalletJ(path, password, getNetworkType().getValue());
Wallet wallet = new Wallet(walletHandle, accountIndex);
manageWallet(wallet);
return wallet;
}
public Wallet openWallet(String path, String password) { public Wallet openWallet(String path, String password) {
long walletHandle = openWalletJ(path, password, getNetworkType().getValue()); long walletHandle = openWalletJ(path, password, getNetworkType().getValue());
Wallet wallet = new Wallet(walletHandle); Wallet wallet = new Wallet(walletHandle);

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M21,18v1c0,1.1 -0.9,2 -2,2L5,21c-1.11,0 -2,-0.9 -2,-2L3,5c0,-1.1 0.89,-2 2,-2h14c1.1,0 2,0.9 2,2v1h-9c-1.11,0 -2,0.9 -2,2v8c0,1.1 0.89,2 2,2h9zM12,16h10L22,8L12,8v8zM16,13.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="20.0"
android:viewportWidth="20.0">
<path
android:fillColor="@color/moneroWhite"
android:pathData="M11,5L9,5L9,9L5,9L5,11L9,11L9,15L11,15L11,11L15,11L15,9L11,9L11,5L11,5ZM10,0C4.5,0 0,4.5 0,10C0,15.5 4.5,20 10,20C15.5,20 20,15.5 20,10C20,4.5 15.5,0 10,0L10,0ZM10,18C5.6,18 2,14.4 2,10C2,5.6 5.6,2 10,2C14.4,2 18,5.6 18,10C18,14.4 14.4,18 10,18L10,18Z" />
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector>

View File

@ -1,22 +1,41 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@drawable/backgound_all" android:fitsSystemWindows="true">
android:gravity="center_horizontal"
android:orientation="vertical">
<com.m2049r.xmrwallet.widget.Toolbar <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
style="@style/ToolBarStyle.Event"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="match_parent"
android:background="@drawable/backgound_toolbar_mainnet" android:background="@drawable/backgound_all"
android:minHeight="?attr/actionBarSize" /> android:gravity="center_horizontal"
android:orientation="vertical">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <com.m2049r.xmrwallet.widget.Toolbar
android:id="@+id/fragment_container" android:id="@+id/toolbar"
android:layout_width="match_parent" style="@style/ToolBarStyle.Event"
android:layout_height="match_parent" /> android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@drawable/backgound_toolbar_mainnet"
android:minHeight="?android:attr/actionBarSize" />
</LinearLayout> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- Container for contents of drawer - use NavigationView to make configuration easier -->
<android.support.design.widget.NavigationView
android:id="@+id/accounts_nav"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header"
app:menu="@menu/drawer_view" />
</android.support.v4.widget.DrawerLayout>

View File

@ -171,6 +171,24 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:shrinkColumns="1"> android:shrinkColumns="1">
<TableRow>
<TextView
style="@style/MoneroLabel.Small"
android:layout_gravity="center_vertical"
android:gravity="end"
android:padding="8dp"
android:text="@string/tx_account" />
<TextView
android:id="@+id/tvAccount"
style="@style/MoneroText"
android:gravity="start"
android:padding="8dp"
android:selectAllOnFocus="true"
android:textIsSelectable="true" />
</TableRow>
<TableRow> <TableRow>
<TextView <TextView

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="192dp"
android:background="@drawable/gradient_all"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvName"
style="@style/MoneroText.Large"
android:textColor="@color/moneroWhite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
tools:text="MyWallet" />
<TextView
android:id="@+id/tvBalance"
style="@style/MoneroLabel.Caps.White"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="end"
tools:text="12.34 XMR" />
</RelativeLayout>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:id="@+id/accounts_list"
android:checkableBehavior="single"
android:orderInCategory="100" />
<group
android:id="@+id/accounts_new"
android:checkableBehavior="none"
android:orderInCategory="200">
<item
android:id="@+id/account_new"
android:icon="@drawable/ic_add_circle_white"
android:title="@string/accounts_drawer_new" />
</group>
</menu>

View File

@ -16,6 +16,13 @@
android:title="@string/menu_info" android:title="@string/menu_info"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/action_rename"
android:icon="@drawable/ic_edit_white_24dp"
android:orderInCategory="100"
android:title="@string/menu_rename"
app:showAsAction="never" />
<item <item
android:id="@+id/action_help_wallet" android:id="@+id/action_help_wallet"
android:icon="@drawable/ic_help_white_24dp" android:icon="@drawable/ic_help_white_24dp"

View File

@ -307,4 +307,12 @@
<string name="fab_restore_viewonly">View Only Wallet wiederherstellen</string> <string name="fab_restore_viewonly">View Only Wallet wiederherstellen</string>
<string name="fab_restore_key">Wallet mit privaten Schlüsseln wiederherstellen</string> <string name="fab_restore_key">Wallet mit privaten Schlüsseln wiederherstellen</string>
<string name="fab_restore_seed">Wallet mit 25 Wörter Seed wiederherstellen</string> <string name="fab_restore_seed">Wallet mit 25 Wörter Seed wiederherstellen</string>
<string name="accounts_drawer_open">Open Accounts Drawer</string>
<string name="accounts_drawer_close">Close Accounts Drawer</string>
<string name="accounts_drawer_new">Create Account</string>
<string name="accounts_drawer_title">Accounts</string>
<string name="accounts_balance">%1$s XMR</string>
<string name="accounts_new">Added new account #%1$d</string>
<string name="tx_account">Account #</string>
</resources> </resources>

View File

@ -292,4 +292,12 @@
<string name="info_send_xmrto_success_order_label">Orden XMR.TO</string> <string name="info_send_xmrto_success_order_label">Orden XMR.TO</string>
<string name="info_xmrto_enabled">Pago en BTC activado, toca para más info.</string> <string name="info_xmrto_enabled">Pago en BTC activado, toca para más info.</string>
<string name="info_crazypass_enabled">CrAzYpass activado, toca para más info.</string> <string name="info_crazypass_enabled">CrAzYpass activado, toca para más info.</string>
<string name="accounts_drawer_open">Open Accounts Drawer</string>
<string name="accounts_drawer_close">Close Accounts Drawer</string>
<string name="accounts_drawer_new">Create Account</string>
<string name="accounts_drawer_title">Accounts</string>
<string name="accounts_balance">%1$s XMR</string>
<string name="accounts_new">Added new account #%1$d</string>
<string name="tx_account">Account #</string>
</resources> </resources>

View File

@ -310,4 +310,12 @@
<string name="fab_restore_viewonly">Restaurer un portefeuille d\'audit</string> <string name="fab_restore_viewonly">Restaurer un portefeuille d\'audit</string>
<string name="fab_restore_key">Restaurer un portefeuille depuis la clef privée</string> <string name="fab_restore_key">Restaurer un portefeuille depuis la clef privée</string>
<string name="fab_restore_seed">Restaurer un portefeuille depuis la phrase mnémonique</string> <string name="fab_restore_seed">Restaurer un portefeuille depuis la phrase mnémonique</string>
<string name="accounts_drawer_open">Open Accounts Drawer</string>
<string name="accounts_drawer_close">Close Accounts Drawer</string>
<string name="accounts_drawer_new">Create Account</string>
<string name="accounts_drawer_title">Accounts</string>
<string name="accounts_balance">%1$s XMR</string>
<string name="accounts_new">Added new account #%1$d</string>
<string name="tx_account">Account #</string>
</resources> </resources>

View File

@ -308,4 +308,12 @@
<string name="fab_restore_viewonly">Recupera un portafoglio solo-visualizzazione</string> <string name="fab_restore_viewonly">Recupera un portafoglio solo-visualizzazione</string>
<string name="fab_restore_key">Recupera un portafoglio dalle chiavi private</string> <string name="fab_restore_key">Recupera un portafoglio dalle chiavi private</string>
<string name="fab_restore_seed">Recupera un portafoglio da un seed di 25 parole</string> <string name="fab_restore_seed">Recupera un portafoglio da un seed di 25 parole</string>
<string name="accounts_drawer_open">Open Accounts Drawer</string>
<string name="accounts_drawer_close">Close Accounts Drawer</string>
<string name="accounts_drawer_new">Create Account</string>
<string name="accounts_drawer_title">Accounts</string>
<string name="accounts_balance">%1$s XMR</string>
<string name="accounts_new">Added new account #%1$d</string>
<string name="tx_account">Account #</string>
</resources> </resources>

View File

@ -306,4 +306,12 @@
<string name="fab_restore_viewonly">Gjenoprett bare-se lommebok</string> <string name="fab_restore_viewonly">Gjenoprett bare-se lommebok</string>
<string name="fab_restore_key">Gjenoprett lommebok fra private nøkler</string> <string name="fab_restore_key">Gjenoprett lommebok fra private nøkler</string>
<string name="fab_restore_seed">Gjenoprett lommebok fra 25-ord seed</string> <string name="fab_restore_seed">Gjenoprett lommebok fra 25-ord seed</string>
<string name="accounts_drawer_open">Open Accounts Drawer</string>
<string name="accounts_drawer_close">Close Accounts Drawer</string>
<string name="accounts_drawer_new">Create Account</string>
<string name="accounts_drawer_title">Accounts</string>
<string name="accounts_balance">%1$s XMR</string>
<string name="accounts_new">Added new account #%1$d</string>
<string name="tx_account">Account #</string>
</resources> </resources>

View File

@ -304,4 +304,12 @@
<string name="fab_restore_viewonly">恢复只读钱包</string> <string name="fab_restore_viewonly">恢复只读钱包</string>
<string name="fab_restore_key">从私钥恢复钱包</string> <string name="fab_restore_key">从私钥恢复钱包</string>
<string name="fab_restore_seed">从25字种子码恢复钱包</string> <string name="fab_restore_seed">从25字种子码恢复钱包</string>
<string name="accounts_drawer_open">Open Accounts Drawer</string>
<string name="accounts_drawer_close">Close Accounts Drawer</string>
<string name="accounts_drawer_new">Create Account</string>
<string name="accounts_drawer_title">Accounts</string>
<string name="accounts_balance">%1$s XMR</string>
<string name="accounts_new">Added new account #%1$d</string>
<string name="tx_account">Account #</string>
</resources> </resources>

View File

@ -305,4 +305,12 @@
<string name="fab_restore_viewonly">回復唯讀錢包</string> <string name="fab_restore_viewonly">回復唯讀錢包</string>
<string name="fab_restore_key">從私鑰回復錢包</string> <string name="fab_restore_key">從私鑰回復錢包</string>
<string name="fab_restore_seed">從25字種子碼回復錢包</string> <string name="fab_restore_seed">從25字種子碼回復錢包</string>
<string name="accounts_drawer_open">Open Accounts Drawer</string>
<string name="accounts_drawer_close">Close Accounts Drawer</string>
<string name="accounts_drawer_new">Create Account</string>
<string name="accounts_drawer_title">Accounts</string>
<string name="accounts_balance">%1$s XMR</string>
<string name="accounts_new">Added new account #%1$d</string>
<string name="tx_account">Account #</string>
</resources> </resources>

View File

@ -256,12 +256,16 @@
<string name="send_create_tx_error_title">Create Transaction Error</string> <string name="send_create_tx_error_title">Create Transaction Error</string>
<string name="accounts_balance">%1$s XMR</string>
<string name="accounts_new">Added new account #%1$d</string>
<string name="tx_list_fee">- Fee %1$s</string> <string name="tx_list_fee">- Fee %1$s</string>
<string name="tx_list_amount_failed">(%1$s)</string> <string name="tx_list_amount_failed">(%1$s)</string>
<string name="tx_list_failed_text">failed</string> <string name="tx_list_failed_text">failed</string>
<string name="tx_list_amount_negative">- %1$s</string> <string name="tx_list_amount_negative">- %1$s</string>
<string name="tx_list_amount_positive">+ %1$s</string> <string name="tx_list_amount_positive">+ %1$s</string>
<string name="tx_account">Account #</string>
<string name="tx_timestamp">Timestamp</string> <string name="tx_timestamp">Timestamp</string>
<string name="tx_id">TX ID</string> <string name="tx_id">TX ID</string>
<string name="tx_key">TX Key</string> <string name="tx_key">TX Key</string>
@ -358,4 +362,10 @@
<string name="fab_restore_viewonly">Restore view-only wallet</string> <string name="fab_restore_viewonly">Restore view-only wallet</string>
<string name="fab_restore_key">Restore wallet from private keys</string> <string name="fab_restore_key">Restore wallet from private keys</string>
<string name="fab_restore_seed">Restore wallet 25 word seed</string> <string name="fab_restore_seed">Restore wallet 25 word seed</string>
<string name="accounts_drawer_open">Open Accounts Drawer</string>
<string name="accounts_drawer_close">Close Accounts Drawer</string>
<string name="accounts_drawer_new">Create Account</string>
<string name="accounts_drawer_title">Accounts</string>
</resources> </resources>

View File

@ -52,6 +52,10 @@
<item name="android:textAllCaps">true</item> <item name="android:textAllCaps">true</item>
</style> </style>
<style name="MoneroLabel.Caps.White">
<item name="android:textColor">@color/moneroWhite</item>
</style>
<style name="MoneroLabel.Caps.Black"> <style name="MoneroLabel.Caps.Black">
<item name="android:textColor">@color/moneroBlack</item> <item name="android:textColor">@color/moneroBlack</item>
</style> </style>