diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2da3e9489..5ab142dd1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -390,6 +390,7 @@ Please submit bug reports, contribute new features and ask questions at
None
SSL/TLS
STARTTLS
+ \"%1$s = %2$s\" is not valid with \"%3$s = %4$s\"
When I delete a message
Do not delete on server
@@ -439,6 +440,7 @@ Please submit bug reports, contribute new features and ask questions at
Username
Password
Authentication
+ \"%1$s = %2$s\" is not valid with \"%3$s = %4$s\"
Invalid setup: %s
diff --git a/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java b/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java
index ea2c1ec2f..493a682de 100644
--- a/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java
+++ b/src/com/fsck/k9/activity/setup/AccountSetupIncoming.java
@@ -12,6 +12,7 @@ import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;
+import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.CompoundButton.OnCheckedChangeListener;
import com.fsck.k9.*;
@@ -59,8 +60,11 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
private TextView mPasswordLabelView;
private EditText mServerView;
private EditText mPortView;
+ private String mCurrentPortViewSetting;
private Spinner mSecurityTypeView;
+ private int mCurrentSecurityTypeViewPosition;
private Spinner mAuthTypeView;
+ private int mCurrentAuthTypeViewPosition;
private CheckBox mImapAutoDetectNamespaceView;
private EditText mImapPathPrefixView;
private EditText mWebdavPathPrefixView;
@@ -136,26 +140,9 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
}
});
- mAuthTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position,
- long id) {
- updateViewFromAuthType();
- }
-
- @Override
- public void onNothingSelected(AdapterView> parent) { /* unused */ }
- });
-
mAuthTypeAdapter = AuthType.getArrayAdapter(this, SslHelper.isClientCertificateSupportAvailable());
mAuthTypeView.setAdapter(mAuthTypeAdapter);
- mUsernameView.addTextChangedListener(validationTextWatcher);
- mPasswordView.addTextChangedListener(validationTextWatcher);
- mServerView.addTextChangedListener(validationTextWatcher);
- mPortView.addTextChangedListener(validationTextWatcher);
- mClientCertificateSpinner.setOnClientCertificateChangedListener(clientCertificateChangedListener);
-
/*
* Only allow digits in the port field.
*/
@@ -182,14 +169,15 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
mSecurityTypeView.setAdapter(securityTypesAdapter);
// Select currently configured security type
- int index = securityTypesAdapter.getPosition(settings.connectionSecurity);
- mSecurityTypeView.setSelection(index, false);
+ mCurrentSecurityTypeViewPosition = securityTypesAdapter.getPosition(settings.connectionSecurity);
+ mSecurityTypeView.setSelection(mCurrentSecurityTypeViewPosition, false);
updateAuthPlainTextFromSecurityType(settings.connectionSecurity);
// The first item is selected if settings.authenticationType is null or is not in mAuthTypeAdapter
- int position = mAuthTypeAdapter.getPosition(settings.authenticationType);
- mAuthTypeView.setSelection(position, false);
+ mCurrentAuthTypeViewPosition = mAuthTypeAdapter.getPosition(settings.authenticationType);
+ mAuthTypeView.setSelection(mCurrentAuthTypeViewPosition, false);
+ updateViewFromAuthType();
if (settings.username != null) {
mUsernameView.setText(settings.username);
@@ -272,27 +260,6 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
throw new Exception("Unknown account type: " + mAccount.getStoreUri());
}
- /*
- * Updates the port when the user changes the security type. This allows
- * us to show a reasonable default which the user can change.
- *
- * Note: It's important that we set the listener *after* an initial option has been
- * selected by the code above. Otherwise the listener might be called after
- * onCreate() has been processed and the current port value set later in this
- * method is overridden with the default port for the selected security type.
- */
- mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position,
- long id) {
- // this indirectly triggers validateFields because the port text is watched
- updatePortFromSecurityType();
- }
-
- @Override
- public void onNothingSelected(AdapterView> parent) { /* unused */ }
- });
-
mCompressionMobile.setChecked(mAccount.useCompression(Account.TYPE_MOBILE));
mCompressionWifi.setChecked(mAccount.useCompression(Account.TYPE_WIFI));
mCompressionOther.setChecked(mAccount.useCompression(Account.TYPE_OTHER));
@@ -306,15 +273,67 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
} else {
updatePortFromSecurityType();
}
+ mCurrentPortViewSetting = mPortView.getText().toString();
mSubscribedFoldersOnly.setChecked(mAccount.subscribedFoldersOnly());
+ initializeViewListeners();
+
validateFields();
} catch (Exception e) {
failure(e);
}
}
+ /**
+ * Called at the end of {@code onCreate()}, after the views have been
+ * initialized, so that the listeners are not triggered during the view
+ * initialization. This avoids needless calls to {@code validateFields()}
+ * which is called at the end of {@code onCreate()}.
+ */
+ private void initializeViewListeners() {
+
+ /*
+ * Updates the port when the user changes the security type. This allows
+ * us to show a reasonable default which the user can change.
+ *
+ * Note: It's important that we set this listener *after* an initial
+ * mSecurityTypeView option has been selected by the code in onCreate().
+ * Otherwise the listener might be called after onCreate() is finished
+ * which would wipe out the initial port value set in onCreate(),
+ * replacing it with the default port for the selected security type.
+ */
+ mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position,
+ long id) {
+ // this indirectly triggers validateFields because the port text is watched
+ updatePortFromSecurityType();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { /* unused */ }
+ });
+
+ mAuthTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position,
+ long id) {
+ updateViewFromAuthType();
+ validateFields();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { /* unused */ }
+ });
+
+ mClientCertificateSpinner.setOnClientCertificateChangedListener(clientCertificateChangedListener);
+ mUsernameView.addTextChangedListener(validationTextWatcher);
+ mPasswordView.addTextChangedListener(validationTextWatcher);
+ mServerView.addTextChangedListener(validationTextWatcher);
+ mPortView.addTextChangedListener(validationTextWatcher);
+ }
+
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@@ -343,7 +362,6 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
mClientCertificateLabelView.setVisibility(View.GONE);
mClientCertificateSpinner.setVisibility(View.GONE);
}
- validateFields();
}
private void validateFields() {
@@ -352,6 +370,45 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
ConnectionSecurity connectionSecurity = (ConnectionSecurity) mSecurityTypeView.getSelectedItem();
boolean hasConnectionSecurity = (!connectionSecurity.equals(ConnectionSecurity.NONE));
+
+ if (isAuthTypeExternal && !hasConnectionSecurity) {
+
+ // Notify user of an invalid combination of AuthType.EXTERNAL & ConnectionSecurity.NONE
+ String toastText = getString(R.string.account_setup_incoming_invalid_setting_combo_notice,
+ getString(R.string.account_setup_incoming_auth_type_label),
+ AuthType.EXTERNAL.toString(),
+ getString(R.string.account_setup_incoming_security_label),
+ ConnectionSecurity.NONE.toString());
+ Toast.makeText(this, toastText, Toast.LENGTH_LONG).show();
+
+ // Reset the views back to their previous settings without recursing through here again
+ OnItemSelectedListener onItemSelectedListener = mAuthTypeView.getOnItemSelectedListener();
+ mAuthTypeView.setOnItemSelectedListener(null);
+ mAuthTypeView.setSelection(mCurrentAuthTypeViewPosition, false);
+ mAuthTypeView.setOnItemSelectedListener(onItemSelectedListener);
+ updateViewFromAuthType();
+
+ onItemSelectedListener = mSecurityTypeView.getOnItemSelectedListener();
+ mSecurityTypeView.setOnItemSelectedListener(null);
+ mSecurityTypeView.setSelection(mCurrentSecurityTypeViewPosition, false);
+ mSecurityTypeView.setOnItemSelectedListener(onItemSelectedListener);
+ updateAuthPlainTextFromSecurityType((ConnectionSecurity) mSecurityTypeView.getSelectedItem());
+
+ mPortView.removeTextChangedListener(validationTextWatcher);
+ mPortView.setText(mCurrentPortViewSetting);
+ mPortView.addTextChangedListener(validationTextWatcher);
+
+ authType = (AuthType) mAuthTypeView.getSelectedItem();
+ isAuthTypeExternal = AuthType.EXTERNAL.equals(authType);
+
+ connectionSecurity = (ConnectionSecurity) mSecurityTypeView.getSelectedItem();
+ hasConnectionSecurity = (!connectionSecurity.equals(ConnectionSecurity.NONE));
+ } else {
+ mCurrentAuthTypeViewPosition = mAuthTypeView.getSelectedItemPosition();
+ mCurrentSecurityTypeViewPosition = mSecurityTypeView.getSelectedItemPosition();
+ mCurrentPortViewSetting = mPortView.getText().toString();
+ }
+
boolean hasValidCertificateAlias = mClientCertificateSpinner.getAlias() != null;
boolean hasValidUserName = Utility.requiredFieldValid(mUsernameView);
diff --git a/src/com/fsck/k9/activity/setup/AccountSetupOutgoing.java b/src/com/fsck/k9/activity/setup/AccountSetupOutgoing.java
index f59abf4e9..dec9b17d1 100644
--- a/src/com/fsck/k9/activity/setup/AccountSetupOutgoing.java
+++ b/src/com/fsck/k9/activity/setup/AccountSetupOutgoing.java
@@ -12,6 +12,7 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.*;
+import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.CompoundButton.OnCheckedChangeListener;
import com.fsck.k9.*;
@@ -46,10 +47,13 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
private TextView mPasswordLabelView;
private EditText mServerView;
private EditText mPortView;
+ private String mCurrentPortViewSetting;
private CheckBox mRequireLoginView;
private ViewGroup mRequireLoginSettingsView;
private Spinner mSecurityTypeView;
+ private int mCurrentSecurityTypeViewPosition;
private Spinner mAuthTypeView;
+ private int mCurrentAuthTypeViewPosition;
private ArrayAdapter mAuthTypeAdapter;
private Button mNextButton;
private Account mAccount;
@@ -106,30 +110,12 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
mNextButton = (Button)findViewById(R.id.next);
mNextButton.setOnClickListener(this);
- mRequireLoginView.setOnCheckedChangeListener(this);
mSecurityTypeView.setAdapter(ConnectionSecurity.getArrayAdapter(this));
mAuthTypeAdapter = AuthType.getArrayAdapter(this, SslHelper.isClientCertificateSupportAvailable());
mAuthTypeView.setAdapter(mAuthTypeAdapter);
- mUsernameView.addTextChangedListener(validationTextWatcher);
- mPasswordView.addTextChangedListener(validationTextWatcher);
- mServerView.addTextChangedListener(validationTextWatcher);
- mPortView.addTextChangedListener(validationTextWatcher);
- mClientCertificateSpinner.setOnClientCertificateChangedListener(clientCertificateChangedListener);
-
- mAuthTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position,
- long id) {
- updateViewFromAuthType();
- }
-
- @Override
- public void onNothingSelected(AdapterView> parent) { /* unused */ }
- });
-
/*
* Only allow digits in the port field.
*/
@@ -155,15 +141,18 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
updateAuthPlainTextFromSecurityType(settings.connectionSecurity);
// The first item is selected if settings.authenticationType is null or is not in mAuthTypeAdapter
- int position = mAuthTypeAdapter.getPosition(settings.authenticationType);
- mAuthTypeView.setSelection(position, false);
+ mCurrentAuthTypeViewPosition = mAuthTypeAdapter.getPosition(settings.authenticationType);
+ mAuthTypeView.setSelection(mCurrentAuthTypeViewPosition, false);
+ updateViewFromAuthType();
// Select currently configured security type
- mSecurityTypeView.setSelection(settings.connectionSecurity.ordinal(), false);
+ mCurrentSecurityTypeViewPosition = settings.connectionSecurity.ordinal();
+ mSecurityTypeView.setSelection(mCurrentSecurityTypeViewPosition, false);
if (settings.username != null) {
mUsernameView.setText(settings.username);
mRequireLoginView.setChecked(true);
+ mRequireLoginSettingsView.setVisibility(View.VISIBLE);
}
if (settings.password != null) {
@@ -174,27 +163,6 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
mClientCertificateSpinner.setAlias(settings.clientCertificateAlias);
}
- /*
- * Updates the port when the user changes the security type. This allows
- * us to show a reasonable default which the user can change.
- *
- * Note: It's important that we set the listener *after* an initial option has been
- * selected by the code above. Otherwise the listener might be called after
- * onCreate() has been processed and the current port value set later in this
- * method is overridden with the default port for the selected security type.
- */
- mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position,
- long id) {
- // this indirectly triggers validateFields because the port text is watched
- updatePortFromSecurityType();
- }
-
- @Override
- public void onNothingSelected(AdapterView> parent) { /* unused */ }
- });
-
if (settings.host != null) {
mServerView.setText(settings.host);
}
@@ -204,6 +172,9 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
} else {
updatePortFromSecurityType();
}
+ mCurrentPortViewSetting = mPortView.getText().toString();
+
+ initializeViewListeners();
validateFields();
} catch (Exception e) {
@@ -215,6 +186,56 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
}
+ /**
+ * Called at the end of {@code onCreate()}, after the views have been
+ * initialized, so that the listeners are not triggered during the view
+ * initialization. This avoids needless calls to {@code validateFields()}
+ * which is called at the end of {@code onCreate()}.
+ */
+ private void initializeViewListeners() {
+
+ /*
+ * Updates the port when the user changes the security type. This allows
+ * us to show a reasonable default which the user can change.
+ *
+ * Note: It's important that we set this listener *after* an initial
+ * mSecurityTypeView option has been selected by the code in onCreate().
+ * Otherwise the listener might be called after onCreate() is finished
+ * which would wipe out the initial port value set in onCreate(),
+ * replacing it with the default port for the selected security type.
+ */
+ mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position,
+ long id) {
+ // this indirectly triggers validateFields because the port text is watched
+ updatePortFromSecurityType();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { /* unused */ }
+ });
+
+ mAuthTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position,
+ long id) {
+ updateViewFromAuthType();
+ validateFields();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) { /* unused */ }
+ });
+
+ mRequireLoginView.setOnCheckedChangeListener(this);
+ mClientCertificateSpinner.setOnClientCertificateChangedListener(clientCertificateChangedListener);
+ mUsernameView.addTextChangedListener(validationTextWatcher);
+ mPasswordView.addTextChangedListener(validationTextWatcher);
+ mServerView.addTextChangedListener(validationTextWatcher);
+ mPortView.addTextChangedListener(validationTextWatcher);
+ }
+
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@@ -243,7 +264,6 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
mClientCertificateLabelView.setVisibility(View.GONE);
mClientCertificateSpinner.setVisibility(View.GONE);
}
- validateFields();
}
private void validateFields() {
@@ -252,6 +272,45 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
ConnectionSecurity connectionSecurity = (ConnectionSecurity) mSecurityTypeView.getSelectedItem();
boolean hasConnectionSecurity = (!connectionSecurity.equals(ConnectionSecurity.NONE));
+
+ if (isAuthTypeExternal && !hasConnectionSecurity) {
+
+ // Notify user of an invalid combination of AuthType.EXTERNAL & ConnectionSecurity.NONE
+ String toastText = getString(R.string.account_setup_outgoing_invalid_setting_combo_notice,
+ getString(R.string.account_setup_incoming_auth_type_label),
+ AuthType.EXTERNAL.toString(),
+ getString(R.string.account_setup_incoming_security_label),
+ ConnectionSecurity.NONE.toString());
+ Toast.makeText(this, toastText, Toast.LENGTH_LONG).show();
+
+ // Reset the views back to their previous settings without recursing through here again
+ OnItemSelectedListener onItemSelectedListener = mAuthTypeView.getOnItemSelectedListener();
+ mAuthTypeView.setOnItemSelectedListener(null);
+ mAuthTypeView.setSelection(mCurrentAuthTypeViewPosition, false);
+ mAuthTypeView.setOnItemSelectedListener(onItemSelectedListener);
+ updateViewFromAuthType();
+
+ onItemSelectedListener = mSecurityTypeView.getOnItemSelectedListener();
+ mSecurityTypeView.setOnItemSelectedListener(null);
+ mSecurityTypeView.setSelection(mCurrentSecurityTypeViewPosition, false);
+ mSecurityTypeView.setOnItemSelectedListener(onItemSelectedListener);
+ updateAuthPlainTextFromSecurityType((ConnectionSecurity) mSecurityTypeView.getSelectedItem());
+
+ mPortView.removeTextChangedListener(validationTextWatcher);
+ mPortView.setText(mCurrentPortViewSetting);
+ mPortView.addTextChangedListener(validationTextWatcher);
+
+ authType = (AuthType) mAuthTypeView.getSelectedItem();
+ isAuthTypeExternal = AuthType.EXTERNAL.equals(authType);
+
+ connectionSecurity = (ConnectionSecurity) mSecurityTypeView.getSelectedItem();
+ hasConnectionSecurity = (!connectionSecurity.equals(ConnectionSecurity.NONE));
+ } else {
+ mCurrentAuthTypeViewPosition = mAuthTypeView.getSelectedItemPosition();
+ mCurrentSecurityTypeViewPosition = mSecurityTypeView.getSelectedItemPosition();
+ mCurrentPortViewSetting = mPortView.getText().toString();
+ }
+
boolean hasValidCertificateAlias = mClientCertificateSpinner.getAlias() != null;
boolean hasValidUserName = Utility.requiredFieldValid(mUsernameView);