From 58329e5212499f0e3ab65b826dade25fb7e837e0 Mon Sep 17 00:00:00 2001 From: pokkst Date: Fri, 7 Oct 2022 16:45:11 -0500 Subject: [PATCH] Add feature to edit/delete nodes from list --- .../wallet/adapter/NodeSelectionAdapter.java | 23 +++++ .../dialog/EditNodeBottomSheetDialog.java | 79 +++++++++++++++ .../NodeSelectionBottomSheetDialog.java | 11 ++- .../fragment/settings/SettingsFragment.java | 52 +++++++++- .../layout/edit_node_bottom_sheet_dialog.xml | 97 +++++++++++++++++++ app/src/main/res/values/strings.xml | 5 + 6 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/net/mynero/wallet/fragment/dialog/EditNodeBottomSheetDialog.java create mode 100644 app/src/main/res/layout/edit_node_bottom_sheet_dialog.xml diff --git a/app/src/main/java/net/mynero/wallet/adapter/NodeSelectionAdapter.java b/app/src/main/java/net/mynero/wallet/adapter/NodeSelectionAdapter.java index 431f70d..1dfd9e0 100644 --- a/app/src/main/java/net/mynero/wallet/adapter/NodeSelectionAdapter.java +++ b/app/src/main/java/net/mynero/wallet/adapter/NodeSelectionAdapter.java @@ -20,6 +20,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import android.widget.Toast; import androidx.recyclerview.widget.RecyclerView; @@ -79,6 +80,7 @@ public class NodeSelectionAdapter extends RecyclerView.Adapter { + if(match) { + Toast.makeText(itemView.getContext(), itemView.getResources().getString(R.string.cant_edit_current_node), Toast.LENGTH_SHORT).show(); + return false; + } else if(isDefaultNode(node)) { + Toast.makeText(itemView.getContext(), itemView.getResources().getString(R.string.cant_edit_default_nodes), Toast.LENGTH_SHORT).show(); + return false; + } else { + return listener.onSelectEditNode(node); + } + }); itemView.setOnClickListener(view -> listener.onSelectNode(node)); } + + private boolean isDefaultNode(Node currentNode) { + boolean isDefault = false; + for(DefaultNodes defaultNode : DefaultNodes.values()) { + if(currentNode.toNodeString().equals(defaultNode.getUri())) + isDefault = true; + } + + return isDefault; + } } } diff --git a/app/src/main/java/net/mynero/wallet/fragment/dialog/EditNodeBottomSheetDialog.java b/app/src/main/java/net/mynero/wallet/fragment/dialog/EditNodeBottomSheetDialog.java new file mode 100644 index 0000000..53abf74 --- /dev/null +++ b/app/src/main/java/net/mynero/wallet/fragment/dialog/EditNodeBottomSheetDialog.java @@ -0,0 +1,79 @@ +package net.mynero.wallet.fragment.dialog; + +import android.content.Context; +import android.os.Bundle; +import android.util.Patterns; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageButton; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import net.mynero.wallet.R; +import net.mynero.wallet.data.Node; +import net.mynero.wallet.service.PrefService; +import net.mynero.wallet.util.Constants; +import net.mynero.wallet.util.Helper; + +import org.json.JSONArray; +import org.json.JSONException; + +public class EditNodeBottomSheetDialog extends BottomSheetDialogFragment { + public EditNodeListener listener = null; + public String nodeString = ""; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.edit_node_bottom_sheet_dialog, null); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + Button deleteNodeButton = view.findViewById(R.id.delete_node_button); + Button doneEditingButton = view.findViewById(R.id.done_editing_button); + EditText addressEditText = view.findViewById(R.id.address_edittext); + EditText nodeNameEditText = view.findViewById(R.id.node_name_edittext); + ImageButton pasteAddressImageButton = view.findViewById(R.id.paste_address_imagebutton); + + Node node = Node.fromString(nodeString); + addressEditText.setText(node.getAddress()); + nodeNameEditText.setText(node.getName()); + + pasteAddressImageButton.setOnClickListener(view1 -> { + Context ctx = getContext(); + if (ctx != null) { + addressEditText.setText(Helper.getClipBoardText(ctx)); + } + }); + deleteNodeButton.setOnClickListener(view1 -> { + listener.onNodeDeleted(Node.fromString(nodeString)); + dismiss(); + }); + doneEditingButton.setOnClickListener(view1 -> { + String nodeAddress = addressEditText.getText().toString(); + String nodeName = nodeNameEditText.getText().toString(); + if (nodeAddress.contains(":") && !nodeName.isEmpty()) { + String[] nodeParts = nodeAddress.split(":"); + if (nodeParts.length == 2) { + String address = nodeParts[0]; + int port = Integer.parseInt(nodeParts[1]); + String newNodeString = address + ":" + port + "/mainnet/" + nodeName; + listener.onNodeEdited(Node.fromString(nodeString), Node.fromString(newNodeString)); + } + } + dismiss(); + }); + } + + public interface EditNodeListener { + void onNodeDeleted(Node node); + void onNodeEdited(Node oldNode, Node newNode); + } +} \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/fragment/dialog/NodeSelectionBottomSheetDialog.java b/app/src/main/java/net/mynero/wallet/fragment/dialog/NodeSelectionBottomSheetDialog.java index f5fb79d..95379c6 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/dialog/NodeSelectionBottomSheetDialog.java +++ b/app/src/main/java/net/mynero/wallet/fragment/dialog/NodeSelectionBottomSheetDialog.java @@ -89,9 +89,18 @@ public class NodeSelectionBottomSheetDialog extends BottomSheetDialogFragment im listener.onNodeSelected(); } + @Override + public boolean onSelectEditNode(Node node) { + if (listener != null) { + listener.onClickedEditNode(node.toNodeString()); + } + dismiss(); + return true; + } + public interface NodeSelectionDialogListener { void onNodeSelected(); - + void onClickedEditNode(String nodeString); void onClickedAddNode(); } } \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java b/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java index 1eac1a9..b6e3baa 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java @@ -27,6 +27,7 @@ import net.mynero.wallet.R; import net.mynero.wallet.data.DefaultNodes; import net.mynero.wallet.data.Node; import net.mynero.wallet.fragment.dialog.AddNodeBottomSheetDialog; +import net.mynero.wallet.fragment.dialog.EditNodeBottomSheetDialog; import net.mynero.wallet.fragment.dialog.WalletKeysBottomSheetDialog; import net.mynero.wallet.fragment.dialog.NodeSelectionBottomSheetDialog; import net.mynero.wallet.fragment.dialog.PasswordBottomSheetDialog; @@ -38,7 +39,9 @@ import net.mynero.wallet.util.Constants; import net.mynero.wallet.util.DayNightMode; import net.mynero.wallet.util.NightmodeHelper; -public class SettingsFragment extends Fragment implements PasswordBottomSheetDialog.PasswordListener, NodeSelectionBottomSheetDialog.NodeSelectionDialogListener, AddNodeBottomSheetDialog.AddNodeListener { +import org.json.JSONArray; + +public class SettingsFragment extends Fragment implements PasswordBottomSheetDialog.PasswordListener, NodeSelectionBottomSheetDialog.NodeSelectionDialogListener, AddNodeBottomSheetDialog.AddNodeListener, EditNodeBottomSheetDialog.EditNodeListener { private SettingsViewModel mViewModel; TextWatcher proxyAddressListener = new TextWatcher() { @@ -235,6 +238,14 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia addNodeDialog.show(getActivity().getSupportFragmentManager(), "add_node_dialog"); } + @Override + public void onClickedEditNode(String nodeString) { + EditNodeBottomSheetDialog editNodeDialog = new EditNodeBottomSheetDialog(); + editNodeDialog.listener = this; + editNodeDialog.nodeString = nodeString; + editNodeDialog.show(getActivity().getSupportFragmentManager(), "edit_node_dialog"); + } + @Override public void onNodeAdded() { NodeSelectionBottomSheetDialog dialog = new NodeSelectionBottomSheetDialog(); @@ -253,4 +264,43 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia } } } + + @Override + public void onNodeDeleted(Node node) { + try { + String nodesArray = PrefService.getInstance().getString(Constants.PREF_CUSTOM_NODES, "[]"); + JSONArray jsonArray = new JSONArray(nodesArray); + for (int i = 0; i < jsonArray.length(); i++) { + String jsonNodeString = jsonArray.getString(i); + Node savedNode = Node.fromString(jsonNodeString); + if (savedNode.toNodeString().equals(node.toNodeString())) + jsonArray.remove(i); + } + saveNodesAndReopen(jsonArray); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onNodeEdited(Node oldNode, Node newNode) { + try { + String nodesArray = PrefService.getInstance().getString(Constants.PREF_CUSTOM_NODES, "[]"); + JSONArray jsonArray = new JSONArray(nodesArray); + for (int i = 0; i < jsonArray.length(); i++) { + String jsonNodeString = jsonArray.getString(i); + Node savedNode = Node.fromString(jsonNodeString); + if (savedNode.toNodeString().equals(oldNode.toNodeString())) + jsonArray.put(i, newNode.toNodeString()); + } + saveNodesAndReopen(jsonArray); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void saveNodesAndReopen(JSONArray jsonArray) { + PrefService.getInstance().edit().putString(Constants.PREF_CUSTOM_NODES, jsonArray.toString()).apply(); + onNodeAdded(); + } } \ No newline at end of file diff --git a/app/src/main/res/layout/edit_node_bottom_sheet_dialog.xml b/app/src/main/res/layout/edit_node_bottom_sheet_dialog.xml new file mode 100644 index 0000000..33ffe15 --- /dev/null +++ b/app/src/main/res/layout/edit_node_bottom_sheet_dialog.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + +