Grant that 'refresh' button embedded in the URL input field does not hide the text...
[pub/Android/ownCloud.git] / src / com / owncloud / android / authentication / AuthenticatorActivity.java
index cc1b648..141cd54 100644 (file)
@@ -3,9 +3,8 @@
  *   Copyright (C) 2012-2013 ownCloud Inc.\r
  *\r
  *   This program is free software: you can redistribute it and/or modify\r
- *   it under the terms of the GNU General Public License as published by\r
- *   the Free Software Foundation, either version 2 of the License, or\r
- *   (at your option) any later version.\r
+ *   it under the terms of the GNU General Public License version 2,\r
+ *   as published by the Free Software Foundation.\r
  *\r
  *   This program is distributed in the hope that it will be useful,\r
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
@@ -20,6 +19,7 @@
 package com.owncloud.android.authentication;\r
 \r
 import com.owncloud.android.AccountUtils;\r
+import com.owncloud.android.Log_OC;\r
 import com.owncloud.android.ui.dialog.SslValidatorDialog;\r
 import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;\r
 import com.owncloud.android.utils.OwnCloudVersion;\r
@@ -42,21 +42,27 @@ import android.content.ContentResolver;
 import android.content.DialogInterface;\r
 import android.content.Intent;\r
 import android.content.SharedPreferences;\r
+import android.graphics.Rect;\r
+import android.graphics.drawable.Drawable;\r
 import android.net.Uri;\r
 import android.os.Bundle;\r
 import android.os.Handler;\r
 import android.preference.PreferenceManager;\r
 import android.text.InputType;\r
-import android.util.Log;\r
+import android.view.KeyEvent;\r
+import android.view.MotionEvent;\r
 import android.view.View;\r
 import android.view.View.OnFocusChangeListener;\r
+import android.view.View.OnTouchListener;\r
 import android.view.Window;\r
+import android.view.inputmethod.EditorInfo;\r
 import android.widget.CheckBox;\r
 import android.widget.EditText;\r
 import android.widget.Button;\r
 import android.widget.ImageView;\r
 import android.widget.TextView;\r
 import android.widget.Toast;\r
+import android.widget.TextView.OnEditorActionListener;\r
 \r
 import com.owncloud.android.R;\r
 \r
@@ -69,7 +75,7 @@ import eu.alefzero.webdav.WebdavClient;
  * @author David A. Velasco\r
  */\r
 public class AuthenticatorActivity extends AccountAuthenticatorActivity\r
-        implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeListener {\r
+        implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeListener, OnEditorActionListener {\r
 \r
     private static final String TAG = AuthenticatorActivity.class.getSimpleName();\r
 \r
@@ -121,7 +127,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
     private byte mAction;\r
     private Account mAccount;\r
     \r
-    private ImageView mRefreshButton;\r
     private ImageView mViewPasswordButton;\r
     private EditText mHostUrlInput;\r
     private EditText mUsernameInput;\r
@@ -147,7 +152,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         \r
         /// set view and get references to view elements\r
         setContentView(R.layout.account_setup);\r
-        mRefreshButton = (ImageView) findViewById(R.id.refreshButton);\r
         mViewPasswordButton = (ImageView) findViewById(R.id.viewPasswordButton);\r
         mHostUrlInput = (EditText) findViewById(R.id.hostUrlInput);\r
         mUsernameInput = (EditText) findViewById(R.id.account_username);\r
@@ -166,7 +170,16 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
 \r
         /// bind view elements to listeners\r
         mHostUrlInput.setOnFocusChangeListener(this);\r
+        mHostUrlInput.setOnTouchListener(new RightDrawableOnTouchListener() {\r
+            @Override\r
+            public boolean onDrawableTouch(final MotionEvent event) {\r
+                AuthenticatorActivity.this.onRefreshClick(mHostUrlInput);\r
+                return true;\r
+            }\r
+        });\r
         mPasswordInput.setOnFocusChangeListener(this);\r
+        mPasswordInput.setImeOptions(EditorInfo.IME_ACTION_DONE);\r
+        mPasswordInput.setOnEditorActionListener(this);\r
         \r
         /// initialization\r
         mAccountMgr = AccountManager.get(this);\r
@@ -179,6 +192,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             mStatusText = mStatusIcon = 0;\r
             mStatusCorrect = false;\r
             mIsSslConn = false;\r
+            updateConnStatus();\r
+            updateAuthStatus();\r
             \r
             /// retrieve extras from intent\r
             String tokenType = getIntent().getExtras().getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE);\r
@@ -271,11 +286,12 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         updateConnStatus();\r
         \r
         /// UI settings depending upon connection\r
-        mOkButton.setEnabled(mStatusCorrect);   // TODO really necessary?\r
-        if (!mStatusCorrect)\r
-            mRefreshButton.setVisibility(View.VISIBLE); // seems that setting visibility is necessary\r
-        else\r
-            mRefreshButton.setVisibility(View.INVISIBLE);\r
+        mOkButton.setEnabled(mStatusCorrect);  \r
+        if (!mStatusCorrect) {\r
+            mHostUrlInput.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_refresh_black, 0);\r
+        } else {\r
+            mHostUrlInput.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);\r
+        }\r
         \r
         /// server data\r
         String ocVersion = savedInstanceState.getString(KEY_OC_VERSION);\r
@@ -302,7 +318,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
      */\r
     @Override\r
     protected void onNewIntent (Intent intent) {\r
-        Log.d(TAG, "onNewIntent()");\r
+        Log_OC.d(TAG, "onNewIntent()");\r
         Uri data = intent.getData();\r
         if (data != null && data.toString().startsWith(getString(R.string.oauth2_redirect_uri))) {\r
             mNewCapturedUriFromOAuth2Redirection = data;\r
@@ -348,7 +364,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
 \r
         /// GET ACCESS TOKEN to the oAuth server \r
         RemoteOperation operation = new OAuth2GetAccessToken(   getString(R.string.oauth2_client_id), \r
-                                                                getString(R.string.oauth2_redirect_uri), // TODO check - necessary here?      \r
+                                                                getString(R.string.oauth2_redirect_uri),       \r
                                                                 getString(R.string.oauth2_grant_type),\r
                                                                 queryParameters);\r
         //WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(getString(R.string.oauth2_url_endpoint_access)), getApplicationContext());\r
@@ -410,7 +426,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             mDiscoveredVersion = null;\r
             mOperationThread = mOcServerChkOperation.execute(client, this, mHandler);\r
         } else {\r
-            mRefreshButton.setVisibility(View.INVISIBLE);\r
+            mHostUrlInput.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);\r
             mStatusText = 0;\r
             mStatusIcon = 0;\r
             updateConnStatus();\r
@@ -477,7 +493,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             mStatusText = R.string.auth_wtf_reenter_URL;\r
             updateConnStatus();\r
             mOkButton.setEnabled(false);\r
-            Log.wtf(TAG,  "The user was allowed to click 'connect' to an unchecked server!!");\r
+            Log_OC.wtf(TAG,  "The user was allowed to click 'connect' to an unchecked server!!");\r
             return;\r
         }\r
         \r
@@ -533,7 +549,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         uriBuilder.appendQueryParameter(OAuth2Constants.KEY_SCOPE, getString(R.string.oauth2_scope));\r
         //uriBuilder.appendQueryParameter(OAuth2Constants.KEY_STATE, whateverwewant);\r
         uri = uriBuilder.build();\r
-        Log.d(TAG, "Starting browser to view " + uri.toString());\r
+        Log_OC.d(TAG, "Starting browser to view " + uri.toString());\r
         Intent i = new Intent(Intent.ACTION_VIEW, uri);\r
         startActivity(i);\r
     }\r
@@ -583,10 +599,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         }\r
         \r
         /// update the visibility of the 'retry connection' button\r
-        if (!mStatusCorrect)\r
-            mRefreshButton.setVisibility(View.VISIBLE);\r
-        else\r
-            mRefreshButton.setVisibility(View.INVISIBLE);\r
+        if (!mStatusCorrect) {\r
+            mHostUrlInput.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_refresh_black, 0);\r
+        } else {\r
+            mHostUrlInput.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);\r
+        }\r
         \r
         /// retrieve discovered version and normalize server URL\r
         mDiscoveredVersion = operation.getDiscoveredVersion();\r
@@ -722,7 +739,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             \r
             /// time to test the retrieved access token on the ownCloud server\r
             mOAuthAccessToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);\r
-            Log.d(TAG, "Got ACCESS TOKEN: " + mOAuthAccessToken);\r
+            Log_OC.d(TAG, "Got ACCESS TOKEN: " + mOAuthAccessToken);\r
             mAuthCheckOperation = new ExistenceCheckOperation("", this, false);\r
             WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this);\r
             client.setBearerCredentials(mOAuthAccessToken);\r
@@ -731,7 +748,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         } else {\r
             updateStatusIconAndText(result);\r
             updateAuthStatus();\r
-            Log.d(TAG, "Access failed: " + result.getLogMessage());\r
+            Log_OC.d(TAG, "Access failed: " + result.getLogMessage());\r
         }\r
     }\r
 \r
@@ -752,7 +769,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         }\r
         \r
         if (result.isSuccess()) {\r
-            Log.d(TAG, "Successful access - time to save the account");\r
+            Log_OC.d(TAG, "Successful access - time to save the account");\r
 \r
             if (mAction == ACTION_CREATE) {\r
                 createAccount();\r
@@ -766,7 +783,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         } else {\r
             updateStatusIconAndText(result);\r
             updateAuthStatus();\r
-            Log.d(TAG, "Access failed: " + result.getLogMessage());\r
+            Log_OC.d(TAG, "Access failed: " + result.getLogMessage());\r
         }\r
     }\r
 \r
@@ -874,7 +891,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             break;\r
         }\r
         default:\r
-            Log.e(TAG, "Incorrect dialog called with id = " + id);\r
+            Log_OC.e(TAG, "Incorrect dialog called with id = " + id);\r
         }\r
     }\r
 \r
@@ -897,7 +914,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
                         @Override\r
                         public void onCancel(DialogInterface dialog) {\r
                             /// TODO study if this is enough\r
-                            Log.i(TAG, "Login canceled");\r
+                            Log_OC.i(TAG, "Login canceled");\r
                             if (mOperationThread != null) {\r
                                 mOperationThread.interrupt();\r
                                 finish();\r
@@ -916,7 +933,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             .setOnCancelListener(new DialogInterface.OnCancelListener() {\r
                 @Override\r
                 public void onCancel(DialogInterface dialog) {\r
-                    Log.i(TAG, "Login canceled");\r
+                    Log_OC.i(TAG, "Login canceled");\r
                     finish();\r
                 }\r
             });\r
@@ -942,7 +959,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             break;\r
         }\r
         default:\r
-            Log.e(TAG, "Incorrect dialog called with id = " + id);\r
+            Log_OC.e(TAG, "Incorrect dialog called with id = " + id);\r
         }\r
         return dialog;\r
     }\r
@@ -965,16 +982,13 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
      * to the last check on the ownCloud server.\r
      */\r
     private void updateConnStatus() {\r
-        ImageView iv = (ImageView) findViewById(R.id.action_indicator);\r
-        TextView tv = (TextView) findViewById(R.id.status_text);\r
+        TextView tv = (TextView) findViewById(R.id.server_status_text);\r
 \r
         if (mStatusIcon == 0 && mStatusText == 0) {\r
-            iv.setVisibility(View.INVISIBLE);\r
             tv.setVisibility(View.INVISIBLE);\r
         } else {\r
-            iv.setImageResource(mStatusIcon);\r
             tv.setText(mStatusText);\r
-            iv.setVisibility(View.VISIBLE);\r
+            tv.setCompoundDrawablesWithIntrinsicBounds(mStatusIcon, 0, 0, 0);\r
             tv.setVisibility(View.VISIBLE);\r
         }\r
     }\r
@@ -1003,7 +1017,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
      * @param view      Refresh 'button'\r
      */\r
     public void onRefreshClick(View view) {\r
-        onFocusChange(mRefreshButton, false);\r
+        onFocusChange(mHostUrlInput, false);\r
     }\r
     \r
     \r
@@ -1083,4 +1097,56 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         showDialog(DIALOG_CERT_NOT_SAVED);\r
     }\r
 \r
+\r
+    /**\r
+     *  Called when the 'action' button in an IME is pressed ('enter' in software keyboard).\r
+     * \r
+     *  Used to trigger the authorization check when the user presses 'enter' after writing the password.\r
+     */\r
+    @Override\r
+    public boolean onEditorAction(TextView inputField, int actionId, KeyEvent event) {\r
+        if (inputField != null && inputField.equals(mPasswordInput) && \r
+                actionId == EditorInfo.IME_ACTION_DONE) {\r
+            if (mOkButton.isEnabled()) {\r
+                mOkButton.performClick();\r
+            }\r
+        }\r
+        return false;   // always return false to grant that the software keyboard is hidden anyway\r
+    }\r
+\r
+    \r
+    private abstract static class RightDrawableOnTouchListener implements OnTouchListener  {\r
+\r
+        private int fuzz = 10;\r
+        \r
+        /**\r
+         * {@inheritDoc}\r
+         */\r
+        @Override\r
+        public boolean onTouch(View view, MotionEvent event) {\r
+            if (event.getAction() == MotionEvent.ACTION_DOWN) {\r
+                Drawable rightDrawable = null;\r
+                if (view instanceof TextView) {\r
+                    Drawable[] drawables = ((TextView)view).getCompoundDrawables();\r
+                    if (drawables.length > 2) {\r
+                        rightDrawable = drawables[2];\r
+                    }\r
+                }\r
+                if (rightDrawable != null) {\r
+                    final int x = (int) event.getX();\r
+                    final int y = (int) event.getY();\r
+                    final Rect bounds = rightDrawable.getBounds();\r
+                    if (x >= (view.getRight() - bounds.width() - fuzz) && x <= (view.getRight() - view.getPaddingRight() + fuzz)\r
+                        && y >= (view.getPaddingTop() - fuzz) && y <= (view.getHeight() - view.getPaddingBottom()) + fuzz) {\r
+                        \r
+                        return onDrawableTouch(event);\r
+                    }\r
+                }\r
+            }\r
+            return false;\r
+        }\r
+        \r
+        public abstract boolean onDrawableTouch(final MotionEvent event);\r
+    }\r
+    \r
 }\r