mirror of https://github.com/m2049r/xmrwallet.git
network slection in menu (#71)
moved code from fragment to activity; dropdownlist is now better
This commit is contained in:
parent
ba408b8889
commit
c4f9e8cf58
|
@ -26,6 +26,7 @@ import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.StrictMode;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
|
||||||
|
@ -39,10 +40,12 @@ import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.m2049r.xmrwallet.layout.DropDownEditText;
|
||||||
import com.m2049r.xmrwallet.license.LicensesFragment;
|
import com.m2049r.xmrwallet.license.LicensesFragment;
|
||||||
import com.m2049r.xmrwallet.model.Wallet;
|
import com.m2049r.xmrwallet.model.Wallet;
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
|
@ -50,12 +53,16 @@ import com.m2049r.xmrwallet.service.WalletService;
|
||||||
import com.m2049r.xmrwallet.util.AsyncExchangeRate;
|
import com.m2049r.xmrwallet.util.AsyncExchangeRate;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
|
||||||
|
import com.m2049r.xmrwallet.util.NodeList;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Socket;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
public class LoginActivity extends AppCompatActivity
|
public class LoginActivity extends AppCompatActivity
|
||||||
implements LoginFragment.Listener, GenerateFragment.Listener,
|
implements LoginFragment.Listener, GenerateFragment.Listener,
|
||||||
|
@ -66,6 +73,9 @@ public class LoginActivity extends AppCompatActivity
|
||||||
static final int DAEMON_TIMEOUT = 500; // deamon must respond in 500ms
|
static final int DAEMON_TIMEOUT = 500; // deamon must respond in 500ms
|
||||||
|
|
||||||
Toolbar toolbar;
|
Toolbar toolbar;
|
||||||
|
EditText etDummy;
|
||||||
|
DropDownEditText etDaemonAddress;
|
||||||
|
ArrayAdapter<String> nodeAdapter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -78,6 +88,45 @@ public class LoginActivity extends AppCompatActivity
|
||||||
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
|
etDummy = (EditText) findViewById(R.id.etDummy);
|
||||||
|
etDaemonAddress = (DropDownEditText) findViewById(R.id.etDaemonAddress);
|
||||||
|
nodeAdapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line);
|
||||||
|
etDaemonAddress.setAdapter(nodeAdapter);
|
||||||
|
|
||||||
|
Helper.hideKeyboard(this);
|
||||||
|
|
||||||
|
etDaemonAddress.setThreshold(0);
|
||||||
|
etDaemonAddress.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
etDaemonAddress.showDropDown();
|
||||||
|
Helper.showKeyboard(LoginActivity.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
etDaemonAddress.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onFocusChange(View v, boolean hasFocus) {
|
||||||
|
if (hasFocus) {
|
||||||
|
etDaemonAddress.showDropDown();
|
||||||
|
Helper.showKeyboard(LoginActivity.this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
etDaemonAddress.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.hideKeyboard(LoginActivity.this);
|
||||||
|
etDummy.requestFocus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
loadPrefs();
|
||||||
|
|
||||||
if (Helper.getWritePermission(this)) {
|
if (Helper.getWritePermission(this)) {
|
||||||
startLoginFragment();
|
startLoginFragment();
|
||||||
} else {
|
} else {
|
||||||
|
@ -96,6 +145,22 @@ public class LoginActivity extends AppCompatActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWalletSelected(final String walletName) {
|
public void onWalletSelected(final String walletName) {
|
||||||
|
String daemon = getDaemon();
|
||||||
|
if (daemon.length() == 0) {
|
||||||
|
Toast.makeText(this, getString(R.string.prompt_daemon_missing), Toast.LENGTH_SHORT).show();
|
||||||
|
etDaemonAddress.requestFocus();
|
||||||
|
Helper.showKeyboard(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkAndSetWalletDaemon(getDaemon(), isTestnet())) {
|
||||||
|
Toast.makeText(this, getString(R.string.warn_daemon_unavailable), Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// looking good
|
||||||
|
savePrefs();
|
||||||
|
|
||||||
if (checkServiceRunning()) return;
|
if (checkServiceRunning()) return;
|
||||||
Log.d(TAG, "selected wallet is ." + walletName + ".");
|
Log.d(TAG, "selected wallet is ." + walletName + ".");
|
||||||
// now it's getting real, check if wallet exists
|
// now it's getting real, check if wallet exists
|
||||||
|
@ -114,6 +179,7 @@ public class LoginActivity extends AppCompatActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWalletDetails(final String walletName) {
|
public void onWalletDetails(final String walletName) {
|
||||||
|
checkAndSetWalletDaemon("", isTestnet()); // just set selected net
|
||||||
Log.d(TAG, "details for wallet ." + walletName + ".");
|
Log.d(TAG, "details for wallet ." + walletName + ".");
|
||||||
if (checkServiceRunning()) return;
|
if (checkServiceRunning()) return;
|
||||||
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
|
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
|
||||||
|
@ -151,6 +217,7 @@ public class LoginActivity extends AppCompatActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWalletReceive(String walletName) {
|
public void onWalletReceive(String walletName) {
|
||||||
|
checkAndSetWalletDaemon("", isTestnet()); // just set selected net
|
||||||
Log.d(TAG, "receive for wallet ." + walletName + ".");
|
Log.d(TAG, "receive for wallet ." + walletName + ".");
|
||||||
if (checkServiceRunning()) return;
|
if (checkServiceRunning()) return;
|
||||||
final File walletFile = Helper.getWalletFile(this, walletName);
|
final File walletFile = Helper.getWalletFile(this, walletName);
|
||||||
|
@ -376,13 +443,16 @@ public class LoginActivity extends AppCompatActivity
|
||||||
try {
|
try {
|
||||||
LoginFragment loginFragment = (LoginFragment)
|
LoginFragment loginFragment = (LoginFragment)
|
||||||
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
||||||
|
if (loginFragment != null) {
|
||||||
loginFragment.loadList();
|
loginFragment.loadList();
|
||||||
|
}
|
||||||
} catch (ClassCastException ex) {
|
} catch (ClassCastException ex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAddWallet() {
|
public void onAddWallet() {
|
||||||
|
checkAndSetWalletDaemon("", isTestnet());
|
||||||
if (checkServiceRunning()) return;
|
if (checkServiceRunning()) return;
|
||||||
startGenerateFragment();
|
startGenerateFragment();
|
||||||
}
|
}
|
||||||
|
@ -477,30 +547,30 @@ public class LoginActivity extends AppCompatActivity
|
||||||
return Helper.getStorageRoot(getApplicationContext());
|
return Helper.getStorageRoot(getApplicationContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
////////////////////////////////////////
|
||||||
|
////////////////////////////////////////
|
||||||
|
|
||||||
public void setTitle(String title) {
|
public void setTitle(String title) {
|
||||||
toolbar.setTitle(title);
|
toolbar.setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSubtitle(String subtitle) {
|
public void setSubtitle(String subtitle) {
|
||||||
toolbar.setSubtitle(subtitle);
|
toolbar.setSubtitle(subtitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void showNet(boolean testnet) {
|
||||||
public void setTestNet(boolean testnet) {
|
|
||||||
if (testnet) {
|
if (testnet) {
|
||||||
toolbar.setBackgroundResource(R.color.colorPrimaryDark);
|
toolbar.setBackgroundResource(R.color.colorPrimaryDark);
|
||||||
} else {
|
} else {
|
||||||
toolbar.setBackgroundResource(R.color.moneroOrange);
|
toolbar.setBackgroundResource(R.color.moneroOrange);
|
||||||
}
|
}
|
||||||
|
setSubtitle(getString(testnet ? R.string.connect_testnet : R.string.connect_mainnet));
|
||||||
}
|
}
|
||||||
////////////////////////////////////////
|
|
||||||
////////////////////////////////////////
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
Log.d(TAG, "onPause()");
|
Log.d(TAG, "onPause()");
|
||||||
|
savePrefs();
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,6 +580,7 @@ public class LoginActivity extends AppCompatActivity
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Log.d(TAG, "onResume()");
|
||||||
|
setTitle(getString(R.string.login_activity_name));
|
||||||
// wait for WalletService to finish
|
// wait for WalletService to finish
|
||||||
if (WalletService.Running && (asyncWaitTask == null)) {
|
if (WalletService.Running && (asyncWaitTask == null)) {
|
||||||
// and show a progress dialog, but only if there isn't one already
|
// and show a progress dialog, but only if there isn't one already
|
||||||
|
@ -920,15 +991,159 @@ public class LoginActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean testnet = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTestnet() {
|
||||||
|
return testnet;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.action_lincense_info:
|
case R.id.action_lincense_info:
|
||||||
LicensesFragment.displayLicensesFragment(getSupportFragmentManager());
|
LicensesFragment.displayLicensesFragment(getSupportFragmentManager());
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.action_testnet:
|
||||||
|
boolean lastState = testnet;//item.isChecked();
|
||||||
|
item.setChecked(!lastState);
|
||||||
|
setNet(!lastState, true); // set and save
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNet(boolean testnet, boolean save) {
|
||||||
|
this.testnet = testnet;
|
||||||
|
showNet(testnet);
|
||||||
|
if (save) {
|
||||||
|
savePrefs(true); // use previous state as we just clicked it
|
||||||
|
}
|
||||||
|
if (testnet) {
|
||||||
|
setDaemon(daemonTestNet);
|
||||||
|
} else {
|
||||||
|
setDaemon(daemonMainNet);
|
||||||
|
}
|
||||||
|
etDummy.requestFocus();
|
||||||
|
Helper.hideKeyboard(this);
|
||||||
|
reloadWalletList();
|
||||||
|
}
|
||||||
|
|
||||||
|
String getDaemon() {
|
||||||
|
return etDaemonAddress.getText().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDaemon(NodeList nodeList) {
|
||||||
|
Log.d(TAG, "setDaemon() " + nodeList.toString());
|
||||||
|
String[] nodes = nodeList.getNodes().toArray(new String[0]);
|
||||||
|
nodeAdapter.clear();
|
||||||
|
nodeAdapter.addAll(nodes);
|
||||||
|
etDaemonAddress.getText().clear();
|
||||||
|
if (nodes.length > 0) {
|
||||||
|
etDaemonAddress.setText(nodes[0]);
|
||||||
|
}
|
||||||
|
etDaemonAddress.dismissDropDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String PREF_DAEMON_TESTNET = "daemon_testnet";
|
||||||
|
private static final String PREF_DAEMON_MAINNET = "daemon_mainnet";
|
||||||
|
private static final String PREF_TESTNET = "testnet";
|
||||||
|
|
||||||
|
private static final String PREF_DAEMONLIST_MAINNET =
|
||||||
|
"node.moneroworld.com:18089;node.xmrbackb.one:18081;node.xmr.be:18081";
|
||||||
|
|
||||||
|
private NodeList daemonTestNet;
|
||||||
|
private NodeList daemonMainNet;
|
||||||
|
|
||||||
|
void loadPrefs() {
|
||||||
|
SharedPreferences sharedPref = getPrefs();
|
||||||
|
|
||||||
|
boolean testnet = sharedPref.getBoolean(PREF_TESTNET, false);
|
||||||
|
daemonMainNet = new NodeList(sharedPref.getString(PREF_DAEMON_MAINNET, PREF_DAEMONLIST_MAINNET));
|
||||||
|
daemonTestNet = new NodeList(sharedPref.getString(PREF_DAEMON_TESTNET, ""));
|
||||||
|
//############### ignore last net state - always start in mainnet (like other clients)
|
||||||
|
// MenuItem net = (MenuItem) getView().findViewById(R.id.action_testnet);
|
||||||
|
// net.setChecked(!mainnet);
|
||||||
|
setNet(testnet, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void savePrefs() {
|
||||||
|
savePrefs(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void savePrefs(boolean usePreviousState) {
|
||||||
|
Log.d(TAG, "SAVE / " + usePreviousState);
|
||||||
|
// save the daemon address for the net
|
||||||
|
boolean testnet = isTestnet() ^ usePreviousState;
|
||||||
|
String daemon = getDaemon();
|
||||||
|
if (testnet) {
|
||||||
|
daemonTestNet.setRecent(daemon);
|
||||||
|
} else {
|
||||||
|
daemonMainNet.setRecent(daemon);
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedPreferences sharedPref = getPrefs();
|
||||||
|
SharedPreferences.Editor editor = sharedPref.edit();
|
||||||
|
//editor.putBoolean(PREF_TESTNET, testnet);
|
||||||
|
editor.putString(PREF_DAEMON_MAINNET, daemonMainNet.toString());
|
||||||
|
editor.putString(PREF_DAEMON_TESTNET, daemonTestNet.toString());
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkAndSetWalletDaemon(String daemon, boolean testnet) {
|
||||||
|
String daemonAddress = "";
|
||||||
|
String username = "";
|
||||||
|
String password = "";
|
||||||
|
if (!daemon.isEmpty()) { // no actual daemon is also fine
|
||||||
|
String a[] = daemon.split("@");
|
||||||
|
if (a.length == 1) { // no credentials
|
||||||
|
daemonAddress = a[0];
|
||||||
|
} else if (a.length == 2) { // credentials
|
||||||
|
String up[] = a[0].split(":");
|
||||||
|
if (up.length != 2) return false;
|
||||||
|
username = up[0];
|
||||||
|
if (!username.isEmpty()) password = up[1];
|
||||||
|
daemonAddress = a[1];
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String da[] = daemonAddress.split(":");
|
||||||
|
if ((da.length > 2) || (da.length < 1)) return false;
|
||||||
|
String host = da[0];
|
||||||
|
int port;
|
||||||
|
if (da.length == 2) {
|
||||||
|
try {
|
||||||
|
port = Integer.parseInt(da[1]);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
port = (testnet ? 28081 : 18081);
|
||||||
|
daemonAddress = daemonAddress + ":" + port;
|
||||||
|
}
|
||||||
|
//Log.d(TAG, "DAEMON " + username + "/" + password + "/" + host + "/" + port);
|
||||||
|
// if (android.os.Build.VERSION.SDK_INT > 9) {
|
||||||
|
StrictMode.ThreadPolicy prevPolicy = StrictMode.getThreadPolicy();
|
||||||
|
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder(prevPolicy).permitNetwork().build();
|
||||||
|
StrictMode.setThreadPolicy(policy);
|
||||||
|
Socket socket = new Socket();
|
||||||
|
long timeA = new Date().getTime();
|
||||||
|
try {
|
||||||
|
socket.connect(new InetSocketAddress(host, port), LoginActivity.DAEMON_TIMEOUT);
|
||||||
|
socket.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Log.d(TAG, "Cannot reach daemon " + host + "/" + port + " because " + ex.getLocalizedMessage());
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
StrictMode.setThreadPolicy(prevPolicy);
|
||||||
|
}
|
||||||
|
long timeB = new Date().getTime();
|
||||||
|
Log.d(TAG, "Daemon is " + (timeB - timeA) + "ms away.");
|
||||||
|
}
|
||||||
|
WalletManager mgr = WalletManager.getInstance();
|
||||||
|
mgr.setDaemon(daemonAddress, testnet, username, password);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,42 +19,31 @@ package com.m2049r.xmrwallet;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.StrictMode;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.BaseAdapter;
|
import android.widget.BaseAdapter;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import android.widget.ToggleButton;
|
|
||||||
|
|
||||||
import com.m2049r.xmrwallet.layout.InstantAutoComplete;
|
|
||||||
import com.m2049r.xmrwallet.model.WalletManager;
|
import com.m2049r.xmrwallet.model.WalletManager;
|
||||||
import com.m2049r.xmrwallet.util.Helper;
|
import com.m2049r.xmrwallet.util.Helper;
|
||||||
import com.m2049r.xmrwallet.util.NodeList;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
@ -75,10 +64,6 @@ public class LoginFragment extends Fragment {
|
||||||
});
|
});
|
||||||
List<String> displayedList = new ArrayList<>();
|
List<String> displayedList = new ArrayList<>();
|
||||||
|
|
||||||
ToggleButton tbMainNet;
|
|
||||||
InstantAutoComplete etDaemonAddress;
|
|
||||||
ArrayAdapter<String> nodeAdapter;
|
|
||||||
|
|
||||||
FloatingActionButton fabAdd;
|
FloatingActionButton fabAdd;
|
||||||
|
|
||||||
Listener activityCallback;
|
Listener activityCallback;
|
||||||
|
@ -103,11 +88,7 @@ public class LoginFragment extends Fragment {
|
||||||
|
|
||||||
void onAddWallet();
|
void onAddWallet();
|
||||||
|
|
||||||
void setTitle(String title);
|
boolean isTestnet();
|
||||||
|
|
||||||
void setSubtitle(String subtitle);
|
|
||||||
|
|
||||||
void setTestNet(boolean testnet);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +106,6 @@ public class LoginFragment extends Fragment {
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
Log.d(TAG, "onPause()");
|
Log.d(TAG, "onPause()");
|
||||||
savePrefs();
|
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +113,6 @@ public class LoginFragment extends Fragment {
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.d(TAG, "onResume()");
|
Log.d(TAG, "onResume()");
|
||||||
activityCallback.setTitle(getString(R.string.login_activity_name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -142,76 +121,23 @@ public class LoginFragment extends Fragment {
|
||||||
Log.d(TAG, "onCreateView");
|
Log.d(TAG, "onCreateView");
|
||||||
View view = inflater.inflate(R.layout.login_fragment, container, false);
|
View view = inflater.inflate(R.layout.login_fragment, container, false);
|
||||||
|
|
||||||
tbMainNet = (ToggleButton) view.findViewById(R.id.tbMainNet);
|
|
||||||
etDaemonAddress = (InstantAutoComplete) view.findViewById(R.id.etDaemonAddress);
|
|
||||||
nodeAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_dropdown_item_1line);
|
|
||||||
etDaemonAddress.setAdapter(nodeAdapter);
|
|
||||||
|
|
||||||
fabAdd = (FloatingActionButton) view.findViewById(R.id.fabAdd);
|
fabAdd = (FloatingActionButton) view.findViewById(R.id.fabAdd);
|
||||||
fabAdd.setOnClickListener(new View.OnClickListener() {
|
fabAdd.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
checkAndSetWalletDaemon("", !isMainNet());
|
|
||||||
activityCallback.onAddWallet();
|
activityCallback.onAddWallet();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Helper.hideKeyboard(getActivity());
|
|
||||||
|
|
||||||
etDaemonAddress.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Helper.showKeyboard(getActivity());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
etDaemonAddress.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.hideKeyboard(getActivity());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tbMainNet.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
boolean mainnet = ((ToggleButton) v).isChecked(); // current state
|
|
||||||
activityCallback.setTestNet(!mainnet);
|
|
||||||
savePrefs(true); // use previous state as we just clicked it
|
|
||||||
if (mainnet) {
|
|
||||||
setDaemon(daemonMainNet);
|
|
||||||
} else {
|
|
||||||
setDaemon(daemonTestNet);
|
|
||||||
}
|
|
||||||
activityCallback.setSubtitle(getString(mainnet ? R.string.connect_mainnet : R.string.connect_testnet));
|
|
||||||
filterList();
|
|
||||||
((BaseAdapter) listView.getAdapter()).notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
loadPrefs();
|
|
||||||
activityCallback.setSubtitle(getString(isMainNet() ? R.string.connect_mainnet : R.string.connect_testnet));
|
|
||||||
|
|
||||||
listView = (ListView) view.findViewById(R.id.list);
|
listView = (ListView) view.findViewById(R.id.list);
|
||||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
|
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
|
||||||
android.R.layout.simple_list_item_1, android.R.id.text1, this.displayedList);
|
android.R.layout.simple_list_item_1, android.R.id.text1, this.displayedList);
|
||||||
|
|
||||||
listView.setAdapter(adapter);
|
listView.setAdapter(adapter);
|
||||||
registerForContextMenu(listView);
|
registerForContextMenu(listView);
|
||||||
|
|
||||||
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
EditText tvDaemonAddress = (EditText) getView().findViewById(R.id.etDaemonAddress);
|
|
||||||
if (tvDaemonAddress.getText().toString().length() == 0) {
|
|
||||||
Toast.makeText(getActivity(), getString(R.string.prompt_daemon_missing), Toast.LENGTH_SHORT).show();
|
|
||||||
tvDaemonAddress.requestFocus();
|
|
||||||
Helper.showKeyboard(getActivity());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String itemValue = (String) listView.getItemAtPosition(position);
|
String itemValue = (String) listView.getItemAtPosition(position);
|
||||||
|
|
||||||
if (itemValue.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
|
if (itemValue.length() <= (WALLETNAME_PREAMBLE_LENGTH)) {
|
||||||
|
@ -219,21 +145,14 @@ public class LoginFragment extends Fragment {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String x = isMainNet() ? "4-" : "9A-";
|
String x = activityCallback.isTestnet() ? "9A-" : "4-";
|
||||||
if (x.indexOf(itemValue.charAt(1)) < 0) {
|
if (x.indexOf(itemValue.charAt(1)) < 0) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
|
Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkAndSetWalletDaemon(getDaemon(), !isMainNet())) {
|
|
||||||
Toast.makeText(getActivity(), getString(R.string.warn_daemon_unavailable), Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// looking good
|
|
||||||
savePrefs();
|
|
||||||
|
|
||||||
String wallet = itemValue.substring(WALLETNAME_PREAMBLE_LENGTH);
|
String wallet = itemValue.substring(WALLETNAME_PREAMBLE_LENGTH);
|
||||||
|
|
||||||
activityCallback.onWalletSelected(wallet);
|
activityCallback.onWalletSelected(wallet);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -244,7 +163,7 @@ public class LoginFragment extends Fragment {
|
||||||
|
|
||||||
private void filterList() {
|
private void filterList() {
|
||||||
displayedList.clear();
|
displayedList.clear();
|
||||||
String x = isMainNet() ? "4" : "9A";
|
String x = activityCallback.isTestnet() ? "9A" : "4";
|
||||||
for (String s : walletList) {
|
for (String s : walletList) {
|
||||||
if (x.indexOf(s.charAt(1)) >= 0) displayedList.add(s);
|
if (x.indexOf(s.charAt(1)) >= 0) displayedList.add(s);
|
||||||
}
|
}
|
||||||
|
@ -252,6 +171,7 @@ public class LoginFragment extends Fragment {
|
||||||
|
|
||||||
public void loadList() {
|
public void loadList() {
|
||||||
Log.d(TAG, "loadList()");
|
Log.d(TAG, "loadList()");
|
||||||
|
// TODO this should probably be in LoginActivity
|
||||||
WalletManager mgr = WalletManager.getInstance();
|
WalletManager mgr = WalletManager.getInstance();
|
||||||
List<WalletManager.WalletInfo> walletInfos =
|
List<WalletManager.WalletInfo> walletInfos =
|
||||||
mgr.findWallets(activityCallback.getStorageRoot());
|
mgr.findWallets(activityCallback.getStorageRoot());
|
||||||
|
@ -272,135 +192,6 @@ public class LoginFragment extends Fragment {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isMainNet() {
|
|
||||||
return tbMainNet.isChecked();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMainNet(boolean mainnet) {
|
|
||||||
tbMainNet.setChecked(mainnet);
|
|
||||||
activityCallback.setTestNet(!mainnet);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
String getDaemon() {
|
|
||||||
return etDaemonAddress.getText().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDaemon(NodeList nodeList) {
|
|
||||||
Log.d(TAG, "setDaemon() " + nodeList.toString());
|
|
||||||
String[] nodes = nodeList.getNodes().toArray(new String[0]);
|
|
||||||
nodeAdapter.clear();
|
|
||||||
nodeAdapter.addAll(nodes);
|
|
||||||
etDaemonAddress.getText().clear();
|
|
||||||
if (nodes.length > 0) {
|
|
||||||
etDaemonAddress.setText(nodes[0]);
|
|
||||||
}
|
|
||||||
etDaemonAddress.dismissDropDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String PREF_DAEMON_TESTNET = "daemon_testnet";
|
|
||||||
private static final String PREF_DAEMON_MAINNET = "daemon_mainnet";
|
|
||||||
private static final String PREF_MAINNET = "mainnet";
|
|
||||||
|
|
||||||
private static final String PREF_DAEMONLIST_MAINNET =
|
|
||||||
"node.moneroworld.com:18089;node.xmrbackb.one:18081;node.xmr.be:18081";
|
|
||||||
|
|
||||||
private NodeList daemonTestNet;
|
|
||||||
private NodeList daemonMainNet;
|
|
||||||
|
|
||||||
void loadPrefs() {
|
|
||||||
SharedPreferences sharedPref = activityCallback.getPrefs();
|
|
||||||
|
|
||||||
boolean mainnet = sharedPref.getBoolean(PREF_MAINNET, false);
|
|
||||||
daemonMainNet = new NodeList(sharedPref.getString(PREF_DAEMON_MAINNET, PREF_DAEMONLIST_MAINNET));
|
|
||||||
daemonTestNet = new NodeList(sharedPref.getString(PREF_DAEMON_TESTNET, ""));
|
|
||||||
|
|
||||||
setMainNet(mainnet);
|
|
||||||
if (mainnet) {
|
|
||||||
setDaemon(daemonMainNet);
|
|
||||||
} else {
|
|
||||||
setDaemon(daemonTestNet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void savePrefs() {
|
|
||||||
savePrefs(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void savePrefs(boolean usePreviousState) {
|
|
||||||
// save the daemon address for the net
|
|
||||||
boolean mainnet = isMainNet() ^ usePreviousState;
|
|
||||||
String daemon = getDaemon();
|
|
||||||
if (mainnet) {
|
|
||||||
daemonMainNet.setRecent(daemon);
|
|
||||||
} else {
|
|
||||||
daemonTestNet.setRecent(daemon);
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedPreferences sharedPref = activityCallback.getPrefs();
|
|
||||||
SharedPreferences.Editor editor = sharedPref.edit();
|
|
||||||
editor.putBoolean(PREF_MAINNET, mainnet);
|
|
||||||
editor.putString(PREF_DAEMON_MAINNET, daemonMainNet.toString());
|
|
||||||
editor.putString(PREF_DAEMON_TESTNET, daemonTestNet.toString());
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkAndSetWalletDaemon(String daemon, boolean testnet) {
|
|
||||||
String daemonAddress = "";
|
|
||||||
String username = "";
|
|
||||||
String password = "";
|
|
||||||
if (!daemon.isEmpty()) { // no actual daemon is also fine
|
|
||||||
String a[] = daemon.split("@");
|
|
||||||
if (a.length == 1) { // no credentials
|
|
||||||
daemonAddress = a[0];
|
|
||||||
} else if (a.length == 2) { // credentials
|
|
||||||
String up[] = a[0].split(":");
|
|
||||||
if (up.length != 2) return false;
|
|
||||||
username = up[0];
|
|
||||||
if (!username.isEmpty()) password = up[1];
|
|
||||||
daemonAddress = a[1];
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String da[] = daemonAddress.split(":");
|
|
||||||
if ((da.length > 2) || (da.length < 1)) return false;
|
|
||||||
String host = da[0];
|
|
||||||
int port;
|
|
||||||
if (da.length == 2) {
|
|
||||||
try {
|
|
||||||
port = Integer.parseInt(da[1]);
|
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
port = (testnet ? 28081 : 18081);
|
|
||||||
daemonAddress = daemonAddress + ":" + port;
|
|
||||||
}
|
|
||||||
//Log.d(TAG, "DAEMON " + username + "/" + password + "/" + host + "/" + port);
|
|
||||||
// if (android.os.Build.VERSION.SDK_INT > 9) {
|
|
||||||
StrictMode.ThreadPolicy prevPolicy = StrictMode.getThreadPolicy();
|
|
||||||
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder(prevPolicy).permitNetwork().build();
|
|
||||||
StrictMode.setThreadPolicy(policy);
|
|
||||||
Socket socket = new Socket();
|
|
||||||
long timeA = new Date().getTime();
|
|
||||||
try {
|
|
||||||
socket.connect(new InetSocketAddress(host, port), LoginActivity.DAEMON_TIMEOUT);
|
|
||||||
socket.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Log.d(TAG, "Cannot reach daemon " + host + "/" + port + " because " + ex.getLocalizedMessage());
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
StrictMode.setThreadPolicy(prevPolicy);
|
|
||||||
}
|
|
||||||
long timeB = new Date().getTime();
|
|
||||||
Log.d(TAG, "Daemon is " + (timeB - timeA) + "ms away.");
|
|
||||||
}
|
|
||||||
WalletManager mgr = WalletManager.getInstance();
|
|
||||||
mgr.setDaemon(daemonAddress, testnet, username, password);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||||
ContextMenu.ContextMenuInfo menuInfo) {
|
ContextMenu.ContextMenuInfo menuInfo) {
|
||||||
|
@ -413,7 +204,7 @@ public class LoginFragment extends Fragment {
|
||||||
public boolean onContextItemSelected(MenuItem item) {
|
public boolean onContextItemSelected(MenuItem item) {
|
||||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
|
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
|
||||||
String listItem = (String) listView.getItemAtPosition(info.position);
|
String listItem = (String) listView.getItemAtPosition(info.position);
|
||||||
String name = nameFromListItem(listItem, !isMainNet());
|
String name = nameFromListItem(listItem, activityCallback.isTestnet());
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
|
Toast.makeText(getActivity(), getString(R.string.panic), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -440,14 +231,10 @@ public class LoginFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showInfo(@NonNull String name) {
|
private void showInfo(@NonNull String name) {
|
||||||
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
|
|
||||||
|
|
||||||
activityCallback.onWalletDetails(name);
|
activityCallback.onWalletDetails(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean showReceive(@NonNull String name) {
|
private boolean showReceive(@NonNull String name) {
|
||||||
checkAndSetWalletDaemon("", !isMainNet()); // just set selected net
|
|
||||||
|
|
||||||
activityCallback.onWalletReceive(name);
|
activityCallback.onWalletReceive(name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,17 +23,17 @@ import android.graphics.Rect;
|
||||||
import android.support.v7.widget.AppCompatAutoCompleteTextView;
|
import android.support.v7.widget.AppCompatAutoCompleteTextView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
public class InstantAutoComplete extends AppCompatAutoCompleteTextView {
|
public class DropDownEditText extends AppCompatAutoCompleteTextView {
|
||||||
|
|
||||||
public InstantAutoComplete(Context context) {
|
public DropDownEditText(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstantAutoComplete(Context arg0, AttributeSet arg1) {
|
public DropDownEditText(Context arg0, AttributeSet arg1) {
|
||||||
super(arg0, arg1);
|
super(arg0, arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstantAutoComplete(Context arg0, AttributeSet arg1, int arg2) {
|
public DropDownEditText(Context arg0, AttributeSet arg1, int arg2) {
|
||||||
super(arg0, arg1, arg2);
|
super(arg0, arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public class InstantAutoComplete extends AppCompatAutoCompleteTextView {
|
||||||
Rect previouslyFocusedRect) {
|
Rect previouslyFocusedRect) {
|
||||||
super.onFocusChanged(focused, direction, previouslyFocusedRect);
|
super.onFocusChanged(focused, direction, previouslyFocusedRect);
|
||||||
if (focused && getAdapter() != null) {
|
if (focused && getAdapter() != null) {
|
||||||
performFiltering(getText(), 0);
|
performFiltering("", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,23 @@
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
layout="@layout/toolbar" />
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etDummy"
|
||||||
|
android:layout_width="0sp"
|
||||||
|
android:layout_height="0sp" />
|
||||||
|
|
||||||
|
<com.m2049r.xmrwallet.layout.DropDownEditText
|
||||||
|
android:id="@+id/etDaemonAddress"
|
||||||
|
style="@style/MoneroEdit"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:hint="@string/prompt_daemon"
|
||||||
|
android:imeOptions="actionDone"
|
||||||
|
android:inputType="textWebEmailAddress|textNoSuggestions"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textIsSelectable="true" />
|
||||||
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/fragment_container"
|
android:id="@+id/fragment_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -4,41 +4,6 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<ToggleButton
|
|
||||||
android:id="@+id/tbMainNet"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checked="false"
|
|
||||||
android:textOff="@string/connect_testnet"
|
|
||||||
android:textOn="@string/connect_mainnet"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<com.m2049r.xmrwallet.layout.InstantAutoComplete
|
|
||||||
android:id="@+id/etDaemonAddress"
|
|
||||||
style="@style/MoneroEdit"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:focusableInTouchMode="true"
|
|
||||||
android:gravity="center"
|
|
||||||
android:hint="@string/prompt_daemon"
|
|
||||||
android:imeOptions="actionDone"
|
|
||||||
android:inputType="textWebEmailAddress|textNoSuggestions"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/tbMainNet"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toLeftOf="@+id/tbMainNet" />
|
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
|
@ -2,10 +2,17 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_testnet"
|
||||||
|
android:checkable="true"
|
||||||
|
android:orderInCategory="100"
|
||||||
|
android:title="@string/menu_testnet"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_lincense_info"
|
android:id="@+id/action_lincense_info"
|
||||||
android:icon="@drawable/ic_info_black_24dp"
|
android:icon="@drawable/ic_info_black_24dp"
|
||||||
android:orderInCategory="100"
|
android:orderInCategory="200"
|
||||||
android:title="@string/menu_about"
|
android:title="@string/menu_about"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<string name="login_activity_name">Monerujo</string>
|
<string name="login_activity_name">Monerujo</string>
|
||||||
<string name="wallet_activity_name">Wallet</string>
|
<string name="wallet_activity_name">Wallet</string>
|
||||||
|
|
||||||
|
<string name="menu_testnet">Testnet</string>
|
||||||
<string name="menu_about">About …</string>
|
<string name="menu_about">About …</string>
|
||||||
|
|
||||||
<string name="menu_info">Details</string>
|
<string name="menu_info">Details</string>
|
||||||
|
|
Loading…
Reference in New Issue