Merge "remove unused --presentationName flag, the presentation is now discovered"
diff --git a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/NavigateFragment.java b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/NavigateFragment.java
index 8ff1a83..073363b 100644
--- a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/NavigateFragment.java
+++ b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/NavigateFragment.java
@@ -339,15 +339,15 @@
             toast("Saving notes");
             mSlides.get(mUserSlideNum).setNotes(notes);
             mDB.setSlideNotes(mDeckId, mUserSlideNum, notes);
-            mNotes.clearFocus();
-            InputMethodManager inputManager =
-                    (InputMethodManager) getContext().
-                            getSystemService(Context.INPUT_METHOD_SERVICE);
-            inputManager.hideSoftInputFromWindow(
-                    getActivity().getCurrentFocus().getWindowToken(),
-                    InputMethodManager.HIDE_NOT_ALWAYS);
-            ((PresentationActivity) getActivity()).setUiImmersive(true);
         }
+        mNotes.clearFocus();
+        InputMethodManager inputManager =
+                (InputMethodManager) getContext().
+                        getSystemService(Context.INPUT_METHOD_SERVICE);
+        inputManager.hideSoftInputFromWindow(
+                getActivity().getCurrentFocus().getWindowToken(),
+                InputMethodManager.HIDE_NOT_ALWAYS);
+        ((PresentationActivity) getActivity()).setUiImmersive(true);
     }
 
     private void unsync() {
@@ -425,7 +425,7 @@
         switch (mRole) {
             case AUDIENCE:
                 db.askQuestion(mDeckId, mPresentationId,
-                        ((PresentationActivity) getActivity()).getFullName());
+                        SignInActivity.getUserName(getActivity()));
                 toast("You have been added to the Q&A queue.");
                 break;
             case PRESENTER:
diff --git a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/NavigationDrawerFragment.java b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/NavigationDrawerFragment.java
index 1891b75..8e57ac4 100644
--- a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/NavigationDrawerFragment.java
+++ b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/NavigationDrawerFragment.java
@@ -62,7 +62,8 @@
     private DrawerLayout mDrawerLayout;
     private ListView mDrawerListView;
     private View mFragmentContainerView;
-    private JSONObject mUserProfile;
+    private String mUserEmail;
+    private String mUserName;
 
     private int mCurrentSelectedPosition = 0;
     private boolean mFromSavedInstanceState;
@@ -79,16 +80,8 @@
         // drawer. See PREF_USER_LEARNED_DRAWER for details.
         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
         mUserLearnedDrawer = prefs.getBoolean(PREF_USER_LEARNED_DRAWER, false);
-        mUserProfile = new JSONObject();
-        // See if user profile has been stored in shared preferences.
-        String userProfileJsonStr = prefs.getString(SignInActivity.PREF_USER_PROFILE_JSON, "");
-        if (!userProfileJsonStr.isEmpty()) {
-            try {
-                mUserProfile = new JSONObject(userProfileJsonStr);
-            } catch (JSONException e) {
-                Log.e(TAG, "Couldn't parse user profile data: " + userProfileJsonStr);
-            }
-        }
+        mUserEmail = SignInActivity.getUserEmail(getActivity());
+        mUserName = SignInActivity.getUserName(getActivity());
 
         if (savedInstanceState != null) {
             mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
@@ -117,30 +110,16 @@
                 selectItem(position);
             }
         });
-        mDrawerListView.setAdapter(new ArrayAdapter<JSONObject>(
+        mDrawerListView.setAdapter(new ArrayAdapter<String>(
                 getActionBar().getThemedContext(),
                 android.R.layout.simple_list_item_activated_2,
                 android.R.id.text1,
-                new JSONObject[]{mUserProfile}) {
+                new String[]{ mUserName }) {
             @Override
             public View getView(int position, View convertView, ViewGroup parent) {
-                JSONObject userProfile = getItem(position);
-                String name = "";
-                String email = "";
-                if (userProfile != null) {
-                    try {
-                        name = userProfile.getString("name");
-                        email = userProfile.getString("email");
-                    } catch (JSONException e) {
-                        Log.e(TAG, "Error reading from user profile: " + e.getMessage());
-                    }
-                }
-                if (name.isEmpty() && email.isEmpty()) {
-                    name = "USER1";
-                }
                 View view = super.getView(position, convertView, parent);
-                ((TextView) view.findViewById(android.R.id.text1)).setText(name);
-                ((TextView) view.findViewById(android.R.id.text2)).setText(email);
+                ((TextView) view.findViewById(android.R.id.text1)).setText(mUserName);
+                ((TextView) view.findViewById(android.R.id.text2)).setText(mUserEmail);
                 return view;
             }
         });
diff --git a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/PresentationActivity.java b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/PresentationActivity.java
index 53c6bfe..4d4f99c 100644
--- a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/PresentationActivity.java
+++ b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/PresentationActivity.java
@@ -64,10 +64,6 @@
      */
     private boolean mShouldBeAdvertising;
     private boolean mIsAdvertising;
-    /**
-     * The human-readable, full name of the user.
-     */
-    private String mFullName;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -104,22 +100,6 @@
             }
         }
 
-        // Get the user's full name from Contacts.
-        Cursor c = getContentResolver().query(ContactsContract.Profile.CONTENT_URI,
-                null, null, null, null);
-        String[] columnNames = c.getColumnNames();
-        mFullName = "Anonymous User";
-        while (c.moveToNext()) {
-            for (int j = 0; j < columnNames.length; j++) {
-                String columnName = columnNames[j];
-                if (!columnName.equals(ContactsContract.Contacts.DISPLAY_NAME)) {
-                    continue;
-                }
-                mFullName = c.getString(c.getColumnIndex(columnName));
-            }
-        }
-        c.close();
-
         // TODO(kash): This is a total hack.  I thought that the deck would be
         // loaded by this point, but we aren't actually guaranteed that.  After
         // this is fixed, we can uncomment handleError in SyncbaseDB.getDeck().
@@ -252,7 +232,7 @@
                     new ParticipantPeer.Server(
                             mDeckFactory.make(mDeck),
                             mDeck.getId(),
-                            new VPerson(blessings.toString(), mFullName),
+                            new VPerson(blessings.toString(), SignInActivity.getUserName(this)),
                             mSyncgroupName,
                             mPresentationId));
             Log.d(TAG, "MT advertising started:");
@@ -382,9 +362,4 @@
     public void setUnsynced() {
         mSynced = false;
     }
-
-    /**
-     * Return the human-readable, full name of the user.
-     */
-    public String getFullName() { return mFullName; }
 }
diff --git a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/SignInActivity.java b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/SignInActivity.java
index 3d225bc..c760e16 100644
--- a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/SignInActivity.java
+++ b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/SignInActivity.java
@@ -14,10 +14,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.database.Cursor;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Message;
 import android.preference.PreferenceManager;
+import android.provider.ContactsContract;
 import android.support.v7.app.AppCompatActivity;
 import android.os.Bundle;
 import android.util.Log;
@@ -42,8 +44,10 @@
 public class SignInActivity extends AppCompatActivity {
     private static final String TAG = "SignInActivity";
 
-    public static final String PREF_USER_ACCOUNT_NAME = "user_account";
-    public static final String PREF_USER_PROFILE_JSON = "user_profile";
+    private static final String PREF_USER_ACCOUNT_NAME = "user_account";
+    private static final String PREF_USER_NAME_FROM_CONTACTS = "user_name_from_contacts";
+    private static final String PREF_USER_NAME_FROM_PROFILE = "user_name_from_profile";
+    private static final String PREF_USER_PROFILE_JSON = "user_profile";
 
     private static final int REQUEST_CODE_PICK_ACCOUNT = 1000;
     private static final int REQUEST_CODE_FETCH_USER_PROFILE_APPROVAL = 1001;
@@ -57,6 +61,43 @@
     private String mAccountName;
     private ProgressDialog mProgressDialog;
 
+    /**
+     * Returns the best-effort email of the signed-in user.
+     */
+    public static String getUserEmail(Context ctx) {
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
+        return prefs.getString(PREF_USER_ACCOUNT_NAME, "");
+    }
+
+    /**
+     * Returns the best-effort full name of the signed-in user.
+     */
+    public static String getUserName(Context ctx) {
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
+        // First try to read the user name we obtained from profile, as it's most accurate.
+        if (prefs.contains(PREF_USER_NAME_FROM_PROFILE)) {
+            return prefs.getString(PREF_USER_NAME_FROM_PROFILE, "Anonymous User");
+        }
+        return prefs.getString(PREF_USER_NAME_FROM_CONTACTS, "Anonymous User");
+    }
+
+    /**
+     * Returns the Google profile information of the signed-in user, or {@code null} if the
+     * profile information couldn't be retrieved.
+     */
+    public static JSONObject getUserProfile(Context ctx) {
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
+        String userProfileJsonStr = prefs.getString(PREF_USER_PROFILE_JSON, "");
+        if (!userProfileJsonStr.isEmpty()) {
+            try {
+                return new JSONObject(userProfileJsonStr);
+            } catch (JSONException e) {
+                Log.e(TAG, "Couldn't parse user profile data: " + userProfileJsonStr);
+            }
+        }
+        return null;
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -107,7 +148,33 @@
         editor.putString(PREF_USER_ACCOUNT_NAME, accountName);
         editor.commit();
 
-        fetchUserProfile();
+        fetchUserNameFromContacts();
+
+        // NOTE(spetrovic): For demo purposes, fetching user profile is too risky as it requires
+        // internet access.  So we disable it for now.
+        //fetchUserProfile();
+        finishActivity();
+    }
+
+    private void fetchUserNameFromContacts() {
+        // Get the user's full name from Contacts.
+        Cursor c = getContentResolver().query(ContactsContract.Profile.CONTENT_URI,
+                null, null, null, null);
+        String[] columnNames = c.getColumnNames();
+        String userName = "Anonymous User";
+        while (c.moveToNext()) {
+            for (int j = 0; j < columnNames.length; j++) {
+                String columnName = columnNames[j];
+                if (!columnName.equals(ContactsContract.Contacts.DISPLAY_NAME)) {
+                    continue;
+                }
+                userName = c.getString(c.getColumnIndex(columnName));
+            }
+        }
+        c.close();
+        SharedPreferences.Editor editor = mPrefs.edit();
+        editor.putString(PREF_USER_NAME_FROM_CONTACTS, userName);
+        editor.commit();
     }
 
     private void fetchUserProfile() {
@@ -144,9 +211,15 @@
         if (userProfile != null) {
             SharedPreferences.Editor editor = mPrefs.edit();
             editor.putString(PREF_USER_PROFILE_JSON, userProfile.toString());
+            try {
+                if (userProfile.has("name") && !userProfile.getString("name").isEmpty()) {
+                    editor.putString(PREF_USER_NAME_FROM_PROFILE, userProfile.getString("name"));
+                }
+            } catch (JSONException e) {
+                Log.e(TAG, "Couldn't read user name from user profile: " + e.getMessage());
+            }
             editor.commit();
         }
-
         finishActivity();
     }
 
diff --git a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/misc/V23Manager.java b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/misc/V23Manager.java
index 5e7c676..cd51312 100644
--- a/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/misc/V23Manager.java
+++ b/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/misc/V23Manager.java
@@ -178,8 +178,7 @@
                         "Cannot get blessings without an activity to return to.");
             }
             // Get the signed-in user's email to generate the blessings from.
-            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(androidCtx);
-            String userEmail = prefs.getString(SignInActivity.PREF_USER_ACCOUNT_NAME, "");
+            String userEmail = SignInActivity.getUserEmail(androidCtx);
             activity.startActivityForResult(
                     BlessingService.newBlessingIntent(androidCtx, userEmail),
                     BLESSING_REQUEST);