From bcfa8ac221e105f21724f84618c3a3aa81f00e22 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Sat, 10 Nov 2018 14:42:05 +0100 Subject: [PATCH] Use an dialog to show advanced settings --- .../github/gotify/login/AdvancedDialog.java | 96 +++++++++++++++++++ .../github/gotify/login/LoginActivity.java | 61 +++++++++--- app/src/main/res/drawable/ic_settings.xml | 4 + app/src/main/res/layout/activity_login.xml | 19 +++- .../res/layout/advanced_settings_dialog.xml | 24 +++++ 5 files changed, 185 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/com/github/gotify/login/AdvancedDialog.java create mode 100644 app/src/main/res/drawable/ic_settings.xml create mode 100644 app/src/main/res/layout/advanced_settings_dialog.xml diff --git a/app/src/main/java/com/github/gotify/login/AdvancedDialog.java b/app/src/main/java/com/github/gotify/login/AdvancedDialog.java new file mode 100644 index 0000000..38dea6a --- /dev/null +++ b/app/src/main/java/com/github/gotify/login/AdvancedDialog.java @@ -0,0 +1,96 @@ +package com.github.gotify.login; + +import android.app.AlertDialog; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.TextView; +import androidx.annotation.Nullable; +import butterknife.BindView; +import butterknife.ButterKnife; +import com.github.gotify.R; + +class AdvancedDialog { + + private Context context; + private ViewHolder holder; + private CompoundButton.OnCheckedChangeListener onCheckedChangeListener; + private Runnable onClickSelectCaCertificate; + private Runnable onClickRemoveCaCertificate; + + AdvancedDialog(Context context) { + this.context = context; + } + + AdvancedDialog onDisableSSLChanged( + CompoundButton.OnCheckedChangeListener onCheckedChangeListener) { + this.onCheckedChangeListener = onCheckedChangeListener; + return this; + } + + AdvancedDialog onClickSelectCaCertificate(Runnable onClickSelectCaCertificate) { + this.onClickSelectCaCertificate = onClickSelectCaCertificate; + return this; + } + + AdvancedDialog onClickRemoveCaCertificate(Runnable onClickRemoveCaCertificate) { + this.onClickRemoveCaCertificate = onClickRemoveCaCertificate; + return this; + } + + AdvancedDialog show(boolean disableSSL, @Nullable String selectedCertificate) { + + View dialogView = + LayoutInflater.from(context).inflate(R.layout.advanced_settings_dialog, null); + holder = new ViewHolder(dialogView); + holder.disableSSL.setChecked(disableSSL); + holder.disableSSL.setOnCheckedChangeListener(onCheckedChangeListener); + + if (selectedCertificate == null) { + showSelectCACertificate(); + } else { + showRemoveCACertificate(selectedCertificate); + } + + new AlertDialog.Builder(context) + .setView(dialogView) + .setTitle("Advanced Settings") + .setPositiveButton("Done", (ignored, ignored2) -> {}) + .show(); + return this; + } + + private void showSelectCACertificate() { + holder.toggleCaCert.setText("Select CA Certificate"); + holder.toggleCaCert.setOnClickListener((a) -> onClickSelectCaCertificate.run()); + holder.selectedCaCertificate.setText("No certificate selected"); + } + + void showRemoveCACertificate(String certificate) { + holder.toggleCaCert.setText("Remove CA Certificate"); + holder.toggleCaCert.setOnClickListener( + (a) -> { + showSelectCACertificate(); + onClickRemoveCaCertificate.run(); + }); + holder.selectedCaCertificate.setText(certificate); + } + + class ViewHolder { + @BindView(R.id.disableSSL) + CheckBox disableSSL; + + @BindView(R.id.toggle_ca_cert) + Button toggleCaCert; + + @BindView(R.id.seleceted_ca_cert) + TextView selectedCaCertificate; + + ViewHolder(View view) { + ButterKnife.bind(this, view); + } + } +} diff --git a/app/src/main/java/com/github/gotify/login/LoginActivity.java b/app/src/main/java/com/github/gotify/login/LoginActivity.java index a0e0d56..1212098 100644 --- a/app/src/main/java/com/github/gotify/login/LoginActivity.java +++ b/app/src/main/java/com/github/gotify/login/LoginActivity.java @@ -7,7 +7,13 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.view.View; -import android.widget.*; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; @@ -34,7 +40,7 @@ import com.github.gotify.init.InitializationActivity; import com.github.gotify.log.Log; import com.github.gotify.log.UncaughtExceptionHandler; import com.squareup.okhttp.HttpUrl; -import java.io.*; +import java.io.InputStream; import java.security.cert.Certificate; import java.security.cert.X509Certificate; @@ -55,8 +61,8 @@ public class LoginActivity extends AppCompatActivity { @BindView(R.id.sslGroup) LinearLayout sslGroup; - @BindView(R.id.showAdvanced) - Button toggleAdvanced; + @BindView(R.id.advanced_settings) + ImageView toggleAdvanced; @BindView(R.id.disableValidateSSL) CheckBox disableSSLValidationCheckBox; @@ -88,6 +94,8 @@ public class LoginActivity extends AppCompatActivity { private boolean disableSSLValidation; private String caCertContents; + private AlertDialog advancedSettingsDialog; + private AdvancedDialog advancedDialog; @Override protected void onCreate(Bundle savedInstanceState) { @@ -101,6 +109,10 @@ public class LoginActivity extends AppCompatActivity { @OnTextChanged(R.id.gotify_url) public void onUrlChange() { + invalidateUrl(); + } + + private void invalidateUrl() { usernameField.setVisibility(View.GONE); passwordField.setVisibility(View.GONE); loginButton.setVisibility(View.GONE); @@ -129,13 +141,29 @@ public class LoginActivity extends AppCompatActivity { .handleInUIThread(this, onValidUrl(fixedUrl), onInvalidUrl(fixedUrl)); } - @OnClick(R.id.showAdvanced) + @OnClick(R.id.advanced_settings) void toggleShowAdvanced() { - showAdvanced = !showAdvanced; - disableSSLValidationCheckBox.setVisibility(showAdvanced ? View.VISIBLE : View.GONE); - selectCACertificate.setVisibility(showAdvanced ? View.VISIBLE : View.GONE); - orTextView.setVisibility(showAdvanced ? View.VISIBLE : View.GONE); - caFileName.setVisibility(showAdvanced ? View.VISIBLE : View.GONE); + String selectedCertName = + caCertContents != null ? getNameOfCertContent(caCertContents) : null; + + advancedDialog = + new AdvancedDialog(this) + .onDisableSSLChanged( + (ignored, disable) -> { + invalidateUrl(); + disableSSLValidation = disable; + }) + .onClickSelectCaCertificate( + () -> { + invalidateUrl(); + doSelectCACertificate(); + }) + .onClickRemoveCaCertificate( + () -> { + invalidateUrl(); + caCertContents = null; + }) + .show(disableSSLValidation, selectedCertName); } @OnCheckedChanged(R.id.disableValidateSSL) @@ -182,12 +210,12 @@ public class LoginActivity extends AppCompatActivity { throw new IllegalArgumentException("file path was invalid"); } - String contents = Utils.readFileFromStream(fileStream); - Certificate ca = CertUtils.parseCertificate(contents); + String content = Utils.readFileFromStream(fileStream); + String name = getNameOfCertContent(content); - caFileName.setText(((X509Certificate) ca).getSubjectDN().getName()); // temporarily set the contents (don't store to settings until they decide to login) - caCertContents = contents; + caCertContents = content; + advancedDialog.showRemoveCACertificate(name); } } catch (Exception e) { Utils.showSnackBar( @@ -195,6 +223,11 @@ public class LoginActivity extends AppCompatActivity { } } + private String getNameOfCertContent(String content) { + Certificate ca = CertUtils.parseCertificate(content); + return ((X509Certificate) ca).getSubjectDN().getName(); + } + private Callback.SuccessCallback onValidUrl(String url) { return (version) -> { settings.url(url); diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml new file mode 100644 index 0000000..4522aca --- /dev/null +++ b/app/src/main/res/drawable/ic_settings.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 59b1355..3870b62 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -202,17 +202,26 @@ android:id="@+id/checkurl" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" - app:layout_constraintWidth_max="280dp" android:background="@color/colorPrimaryDark" android:text="@string/check_url" android:textColor="@android:color/white" android:visibility="visible" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/gotify_url" /> + app:layout_constraintEnd_toStartOf="@+id/advanced_settings" + app:layout_constraintStart_toStartOf="@+id/gotify_url" + app:layout_constraintTop_toBottomOf="@+id/gotify_url" + app:layout_constraintWidth_max="280dp" /> + diff --git a/app/src/main/res/layout/advanced_settings_dialog.xml b/app/src/main/res/layout/advanced_settings_dialog.xml new file mode 100644 index 0000000..4fb4cb6 --- /dev/null +++ b/app/src/main/res/layout/advanced_settings_dialog.xml @@ -0,0 +1,24 @@ + + + + + +