From a9700a076d09989a5c6ae77888096e1ad5e4ffbf Mon Sep 17 00:00:00 2001 From: Kyle Horimoto Date: Fri, 18 Sep 2015 12:22:29 -0700 Subject: Add EditHostActivity. --- app/src/main/AndroidManifest.xml | 9 + .../main/java/org/connectbot/EditHostActivity.java | 43 +++ .../java/org/connectbot/HostEditorFragment.java | 339 +++++++++++++++++++++ .../main/java/org/connectbot/bean/HostBean.java | 61 ++++ app/src/main/res/drawable-hdpi/ic_expand_less.png | Bin 0 -> 156 bytes app/src/main/res/drawable-hdpi/ic_expand_more.png | Bin 0 -> 159 bytes app/src/main/res/drawable-mdpi/ic_expand_less.png | Bin 0 -> 129 bytes app/src/main/res/drawable-mdpi/ic_expand_more.png | Bin 0 -> 129 bytes app/src/main/res/drawable-xhdpi/ic_expand_less.png | Bin 0 -> 179 bytes app/src/main/res/drawable-xhdpi/ic_expand_more.png | Bin 0 -> 182 bytes .../main/res/drawable-xxhdpi/ic_expand_less.png | Bin 0 -> 230 bytes .../main/res/drawable-xxhdpi/ic_expand_more.png | Bin 0 -> 237 bytes .../main/res/drawable-xxxhdpi/ic_expand_less.png | Bin 0 -> 284 bytes .../main/res/drawable-xxxhdpi/ic_expand_more.png | Bin 0 -> 287 bytes app/src/main/res/layout/activity_edit_host.xml | 23 ++ app/src/main/res/layout/fragment_host_editor.xml | 137 +++++++++ app/src/main/res/values/strings.xml | 4 + app/src/main/res/values/styles.xml | 7 + 18 files changed, 623 insertions(+) create mode 100644 app/src/main/java/org/connectbot/EditHostActivity.java create mode 100644 app/src/main/java/org/connectbot/HostEditorFragment.java create mode 100644 app/src/main/res/drawable-hdpi/ic_expand_less.png create mode 100644 app/src/main/res/drawable-hdpi/ic_expand_more.png create mode 100644 app/src/main/res/drawable-mdpi/ic_expand_less.png create mode 100644 app/src/main/res/drawable-mdpi/ic_expand_more.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_expand_less.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_expand_more.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_expand_less.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_expand_more.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_expand_less.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_expand_more.png create mode 100644 app/src/main/res/layout/activity_edit_host.xml create mode 100644 app/src/main/res/layout/fragment_host_editor.xml (limited to 'app') diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 873332f..e863b21 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -84,6 +84,15 @@ android:value="org.connectbot.PubkeyListActivity"/> + + + + + transportSelection = new ArrayAdapter<>( + getActivity(), + android.R.layout.simple_spinner_item, + TransportFactory.getTransportNames()); + transportSelection.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mTransportSpinner.setAdapter(transportSelection); + mTransportSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + String protocol = (String) mTransportSpinner.getSelectedItem(); + if (protocol == null) { + // During initialization, protocol can be null before the list of dropdown items + // has been generated. Return early in that case. + return; + } + + mHost.setProtocol(protocol); + mHost.setPort(TransportFactory.getTransport(protocol).getDefaultPort()); + + mQuickConnectContainer.setHint( + TransportFactory.getFormatHint(protocol, getActivity())); + + // Different protocols have different field types, so show only the fields needed. + if (SSH.getProtocolName().equals(protocol)) { + mUsernameContainer.setVisibility(View.VISIBLE); + mHostnameContainer.setVisibility(View.VISIBLE); + mPortContainer.setVisibility(View.VISIBLE); + mExpandCollapseButton.setVisibility(View.VISIBLE); + } else if (Telnet.getProtocolName().equals(protocol)) { + mUsernameContainer.setVisibility(View.GONE); + mHostnameContainer.setVisibility(View.VISIBLE); + mPortContainer.setVisibility(View.VISIBLE); + mExpandCollapseButton.setVisibility(View.VISIBLE); + } else { + // Local protocol has only one field, so no need to show the URI parts + // container. + setUriPartsContainerExpanded(false); + mExpandCollapseButton.setVisibility(View.INVISIBLE); + } + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + + mQuickConnectContainer = + (TextInputLayout) view.findViewById(R.id.quickconnect_field_container); + + mQuickConnectField = (EditText) view.findViewById(R.id.quickconnect_field); + String oldQuickConnect = savedInstanceState == null ? + null : savedInstanceState.getString(ARG_QUICKCONNECT_STRING); + mQuickConnectField.setText(oldQuickConnect == null ? mHost.toString() : oldQuickConnect); + mQuickConnectField.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + + @Override + public void afterTextChanged(Editable s) { + if (mTransportSpinner.getSelectedItem() == null) { + // During initialization, protocol can be null before the list of dropdown items + // has been generated. Return early in that case. + return; + } + + if (!mUriFieldEditInProgress) { + applyQuickConnectString( + s.toString(), (String) mTransportSpinner.getSelectedItem()); + + mUriFieldEditInProgress = true; + mUsernameField.setText(mHost.getUsername()); + mHostnameField.setText(mHost.getHostname()); + mPortField.setText(Integer.toString(mHost.getPort())); + mUriFieldEditInProgress = false; + } + } + }); + + mExpandCollapseButton = (ImageButton) view.findViewById(R.id.expand_collapse_button); + mExpandCollapseButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + setUriPartsContainerExpanded(!mIsUriEditorExpanded); + } + }); + + mUriPartsContainer = view.findViewById(R.id.uri_parts_container); + + mUsernameContainer = view.findViewById(R.id.username_field_container); + mUsernameField = (EditText) view.findViewById(R.id.username_edit_text); + mUsernameField.setText(mHost.getUsername()); + mUsernameField.addTextChangedListener(new UriDataUpdater(HostDatabase.FIELD_HOST_USERNAME)); + + mHostnameContainer = view.findViewById(R.id.hostname_field_container); + mHostnameField = (EditText) view.findViewById(R.id.hostname_edit_text); + mHostnameField.setText(mHost.getHostname()); + mHostnameField.addTextChangedListener(new UriDataUpdater(HostDatabase.FIELD_HOST_HOSTNAME)); + + mPortContainer = view.findViewById(R.id.port_field_container); + mPortField = (EditText) view.findViewById(R.id.port_edit_text); + mPortField.setText(Integer.toString(mHost.getPort())); + mPortField.addTextChangedListener(new UriDataUpdater(HostDatabase.FIELD_HOST_PORT)); + + setUriPartsContainerExpanded(mIsUriEditorExpanded); + + return view; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + try { + mListener = (Listener) context; + } catch (ClassCastException e) { + throw new ClassCastException(context.toString() + " must implement Listener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + @Override + public void onSaveInstanceState(Bundle savedInstanceState) { + super.onSaveInstanceState(savedInstanceState); + + savedInstanceState.putParcelable(ARG_EXISTING_HOST, mHost.getValues()); + savedInstanceState.putBoolean(ARG_IS_EXPANDED, mIsUriEditorExpanded); + savedInstanceState.putString( + ARG_QUICKCONNECT_STRING, mQuickConnectField.getText().toString()); + } + + private void setUriPartsContainerExpanded(boolean expanded) { + mIsUriEditorExpanded = expanded; + + if (mIsUriEditorExpanded) { + mExpandCollapseButton.setImageResource(R.drawable.ic_expand_less); + mUriPartsContainer.setVisibility(View.VISIBLE); + } else { + mExpandCollapseButton.setImageResource(R.drawable.ic_expand_more); + mUriPartsContainer.setVisibility(View.GONE); + } + } + + /** + * Applies the quick-connect URI entered in the field by copying its URI parts to mHost's + * fields. + * @param quickConnectString The URI entered in the quick-connect field. + * @param protocol The protocol for this connection. + */ + private void applyQuickConnectString(String quickConnectString, String protocol) { + if (quickConnectString == null || protocol == null) + return; + + Uri uri = TransportFactory.getUri(protocol, quickConnectString); + if (uri == null) { + // If the URI was invalid, null out the associated fields. + mHost.setProtocol(protocol); + mHost.setUsername(null); + mHost.setHostname(null); + mHost.setNickname(null); + mHost.setPort(TransportFactory.getTransport(protocol).getDefaultPort()); + return; + } + + HostBean host = TransportFactory.getTransport(protocol).createHost(uri); + mHost.setProtocol(host.getProtocol()); + mHost.setUsername(host.getUsername()); + mHost.setHostname(host.getHostname()); + mHost.setNickname(host.getNickname()); + mHost.setPort(host.getPort()); + } + + public interface Listener { + public void onHostUpdated(HostBean host); + } + + private class UriDataUpdater implements TextWatcher { + + private final String mFieldType; + + public UriDataUpdater(String fieldType) { + mFieldType = fieldType; + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + + @Override + public void afterTextChanged(Editable s) { + String text = s.toString(); + + if (HostDatabase.FIELD_HOST_USERNAME.equals(mFieldType)) { + mHost.setUsername(text); + } else if (HostDatabase.FIELD_HOST_HOSTNAME.equals(mFieldType)) { + mHost.setHostname(text); + } else if (HostDatabase.FIELD_HOST_PORT.equals(mFieldType)) { + try { + mHost.setPort(Integer.parseInt(text)); + } catch (NumberFormatException e) { + return; + } + } else { + throw new RuntimeException("Invalid field type."); + } + + if (!mUriFieldEditInProgress) { + mUriFieldEditInProgress = true; + mQuickConnectField.setText(mHost.toString()); + mUriFieldEditInProgress = false; + } + } + } +} diff --git a/app/src/main/java/org/connectbot/bean/HostBean.java b/app/src/main/java/org/connectbot/bean/HostBean.java index 93d7716..1fbb9be 100644 --- a/app/src/main/java/org/connectbot/bean/HostBean.java +++ b/app/src/main/java/org/connectbot/bean/HostBean.java @@ -17,6 +17,10 @@ package org.connectbot.bean; +import org.connectbot.transport.Local; +import org.connectbot.transport.SSH; +import org.connectbot.transport.Telnet; +import org.connectbot.transport.TransportFactory; import org.connectbot.util.HostDatabase; import android.content.ContentValues; @@ -226,6 +230,29 @@ public class HostBean extends AbstractBean { return values; } + public static HostBean fromContentValues(ContentValues values) { + HostBean host = new HostBean(); + host.setNickname(values.getAsString(HostDatabase.FIELD_HOST_NICKNAME)); + host.setProtocol(values.getAsString(HostDatabase.FIELD_HOST_PROTOCOL)); + host.setUsername(values.getAsString(HostDatabase.FIELD_HOST_USERNAME)); + host.setHostname(values.getAsString(HostDatabase.FIELD_HOST_HOSTNAME)); + host.setPort(values.getAsInteger(HostDatabase.FIELD_HOST_PORT)); + host.setLastConnect(values.getAsLong(HostDatabase.FIELD_HOST_LASTCONNECT)); + host.setColor(values.getAsString(HostDatabase.FIELD_HOST_COLOR)); + host.setUseKeys(Boolean.valueOf(values.getAsString(HostDatabase.FIELD_HOST_USEKEYS))); + host.setUseAuthAgent(values.getAsString(HostDatabase.FIELD_HOST_USEAUTHAGENT)); + host.setPostLogin(values.getAsString(HostDatabase.FIELD_HOST_POSTLOGIN)); + host.setPubkeyId(values.getAsLong(HostDatabase.FIELD_HOST_PUBKEYID)); + host.setWantSession(Boolean.valueOf(values.getAsString(HostDatabase.FIELD_HOST_WANTSESSION))); + host.setDelKey(values.getAsString(HostDatabase.FIELD_HOST_DELKEY)); + host.setFontSize(values.getAsInteger(HostDatabase.FIELD_HOST_FONTSIZE)); + host.setCompression(Boolean.valueOf(values.getAsString(HostDatabase.FIELD_HOST_COMPRESSION))); + host.setEncoding(values.getAsString(HostDatabase.FIELD_HOST_ENCODING)); + host.setStayConnected(values.getAsBoolean(HostDatabase.FIELD_HOST_STAYCONNECTED)); + host.setQuickDisconnect(values.getAsBoolean(HostDatabase.FIELD_HOST_QUICKDISCONNECT)); + return host; + } + @Override public boolean equals(Object o) { if (o == null || !(o instanceof HostBean)) @@ -302,4 +329,38 @@ public class HostBean extends AbstractBean { return Uri.parse(sb.toString()); } + /** + * Generates a "pretty" string to be used in the quick-connect host edit view. + */ + @Override + public String toString() { + if (protocol == null) + return ""; + + int defaultPort = TransportFactory.getTransport(protocol).getDefaultPort(); + + if (SSH.getProtocolName().equals(protocol)) { + if (username == null || hostname == null || + username.equals("") || hostname.equals("")) + return ""; + + if (port == defaultPort) + return username + "@" + hostname; + else + return username + "@" + hostname + ":" + port; + } else if (Telnet.getProtocolName().equals(protocol)) { + if (hostname == null || hostname.equals("")) + return ""; + else if (port == defaultPort) + return hostname; + else + return hostname + ":" + port; + } else if (Local.getProtocolName().equals(protocol)) { + return nickname; + } + + // Fail gracefully. + return ""; + } + } diff --git a/app/src/main/res/drawable-hdpi/ic_expand_less.png b/app/src/main/res/drawable-hdpi/ic_expand_less.png new file mode 100644 index 0000000..dea8988 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_expand_less.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_expand_more.png b/app/src/main/res/drawable-hdpi/ic_expand_more.png new file mode 100644 index 0000000..022e057 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_expand_more.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_expand_less.png b/app/src/main/res/drawable-mdpi/ic_expand_less.png new file mode 100644 index 0000000..a2e4baa Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_expand_less.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_expand_more.png b/app/src/main/res/drawable-mdpi/ic_expand_more.png new file mode 100644 index 0000000..910bb2a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_expand_more.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_expand_less.png b/app/src/main/res/drawable-xhdpi/ic_expand_less.png new file mode 100644 index 0000000..ae36d91 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_expand_less.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_expand_more.png b/app/src/main/res/drawable-xhdpi/ic_expand_more.png new file mode 100644 index 0000000..c42e2a0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_expand_more.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_expand_less.png b/app/src/main/res/drawable-xxhdpi/ic_expand_less.png new file mode 100644 index 0000000..62fc386 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_expand_less.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_expand_more.png b/app/src/main/res/drawable-xxhdpi/ic_expand_more.png new file mode 100644 index 0000000..dbc0b20 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_expand_more.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_expand_less.png b/app/src/main/res/drawable-xxxhdpi/ic_expand_less.png new file mode 100644 index 0000000..4261551 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_expand_less.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_expand_more.png b/app/src/main/res/drawable-xxxhdpi/ic_expand_more.png new file mode 100644 index 0000000..2859a6f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_expand_more.png differ diff --git a/app/src/main/res/layout/activity_edit_host.xml b/app/src/main/res/layout/activity_edit_host.xml new file mode 100644 index 0000000..f2aa96c --- /dev/null +++ b/app/src/main/res/layout/activity_edit_host.xml @@ -0,0 +1,23 @@ + + + diff --git a/app/src/main/res/layout/fragment_host_editor.xml b/app/src/main/res/layout/fragment_host_editor.xml new file mode 100644 index 0000000..a88c1d4 --- /dev/null +++ b/app/src/main/res/layout/fragment_host_editor.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f41d10b..aa40906 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -594,4 +594,8 @@ F11 F12 + Connection type: + Protocol + Expand + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 322f5e1..af3bd79 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -76,4 +76,11 @@ + + + -- cgit v1.2.3