TODOs: Upon creating, enter the list

This seemed like the right thing to do. After creating a list, you
would probably edit it immediately, so that's what happens now.

In order for that metadata to arrive earlier, syncgroup creation was
deferred and can be done at any time. Since this means that the userdata
collection may get data earlier than expected, the number of allowed
join retries was bumped up to 10.

Change-Id: I657be219aeed88f419a5696f1887326f2a9e040c
diff --git a/app/src/firebase/java/io/v/todos/persistence/firebase/FirebaseMain.java b/app/src/firebase/java/io/v/todos/persistence/firebase/FirebaseMain.java
index 433d43e..b9e9fe2 100644
--- a/app/src/firebase/java/io/v/todos/persistence/firebase/FirebaseMain.java
+++ b/app/src/firebase/java/io/v/todos/persistence/firebase/FirebaseMain.java
@@ -66,8 +66,10 @@
     }
 
     @Override
-    public void addTodoList(ListSpec listSpec) {
-        mTodoLists.push().setValue(listSpec);
+    public String addTodoList(ListSpec listSpec) {
+        Firebase newListItem = mTodoLists.push();
+        newListItem.setValue(listSpec);
+        return newListItem.getKey();
     }
 
     @Override
diff --git a/app/src/main/java/io/v/todos/MainActivity.java b/app/src/main/java/io/v/todos/MainActivity.java
index 520816c..113fc17 100644
--- a/app/src/main/java/io/v/todos/MainActivity.java
+++ b/app/src/main/java/io/v/todos/MainActivity.java
@@ -6,6 +6,7 @@
 
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.Handler;
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.helper.ItemTouchHelper;
@@ -49,11 +50,7 @@
             @Override
             public void onClick(View view) {
                 String fbKey = (String)view.getTag();
-
-                Intent intent = new Intent(MainActivity.this, TodoListActivity.class);
-                intent.putExtra(INTENT_SNACKOO_KEY, fbKey);
-                startActivity(intent);
-                overridePendingTransition(R.anim.right_slide_in, R.anim.left_slide_out);
+                enterList(fbKey);
             }
         });
 
@@ -119,7 +116,7 @@
                 // probably better just to rebind.
                 TodoListViewHolder vh = (TodoListViewHolder) mRecyclerView
                         .findViewHolderForAdapterPosition(end);
-                if (vh.itemView.getAlpha() < 1) {
+                if (vh != null && vh.itemView.getAlpha() < 1) {
                     mAdapter.bindViewHolder(vh, end);
                 } else {
                     mAdapter.notifyItemChanged(end);
@@ -140,11 +137,25 @@
         UIUtil.showAddDialog(this, "New Todo List", new UIUtil.DialogResponseListener() {
             @Override
             public void handleResponse(String response) {
-                mPersistence.addTodoList(new ListSpec(response));
+                String newKey = mPersistence.addTodoList(new ListSpec(response));
+                enterList(newKey);
             }
         });
     }
 
+    private void enterList(final String listKey) {
+        new Handler().postDelayed(new Runnable() {
+            @Override
+            public void run() {
+
+                Intent intent = new Intent(MainActivity.this, TodoListActivity.class);
+                intent.putExtra(INTENT_SNACKOO_KEY, listKey);
+                startActivity(intent);
+                overridePendingTransition(R.anim.right_slide_in, R.anim.left_slide_out);
+            }
+        }, 100); // Use a short delay to allow the keyboard to disappear.
+    }
+
     // The following methods are boilerplate for handling the Menu in the top right corner.
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
diff --git a/app/src/main/java/io/v/todos/persistence/MainPersistence.java b/app/src/main/java/io/v/todos/persistence/MainPersistence.java
index 11327e2..e078ea3 100644
--- a/app/src/main/java/io/v/todos/persistence/MainPersistence.java
+++ b/app/src/main/java/io/v/todos/persistence/MainPersistence.java
@@ -8,6 +8,6 @@
 import io.v.todos.model.ListSpec;
 
 public interface MainPersistence extends Persistence {
-    void addTodoList(ListSpec listSpec);
+    String addTodoList(ListSpec listSpec);
     void deleteTodoList(String key);
 }
diff --git a/app/src/mock/java/io/v/todos/persistence/PersistenceFactory.java b/app/src/mock/java/io/v/todos/persistence/PersistenceFactory.java
index 253b2d1..f3da934 100644
--- a/app/src/mock/java/io/v/todos/persistence/PersistenceFactory.java
+++ b/app/src/mock/java/io/v/todos/persistence/PersistenceFactory.java
@@ -51,7 +51,8 @@
 
     static class MockMainPersistence implements MainPersistence {
         @Override
-        public void addTodoList(ListSpec listSpec) {
+        public String addTodoList(ListSpec listSpec) {
+            return "";
         }
 
         @Override
diff --git a/app/src/syncbase/java/io/v/todos/persistence/syncbase/SyncbaseMain.java b/app/src/syncbase/java/io/v/todos/persistence/syncbase/SyncbaseMain.java
index eb8d410..4534380 100644
--- a/app/src/syncbase/java/io/v/todos/persistence/syncbase/SyncbaseMain.java
+++ b/app/src/syncbase/java/io/v/todos/persistence/syncbase/SyncbaseMain.java
@@ -45,7 +45,7 @@
     private static final String
             TAG = SyncbaseMain.class.getSimpleName();
 
-    private static int DEFAULT_MAX_JOIN_ATTEMPTS = 5;
+    private static int DEFAULT_MAX_JOIN_ATTEMPTS = 10;
 
     private final IdGenerator mIdGenerator = new IdGenerator(IdAlphabets.COLLECTION_ID, true);
     private final Map<String, MainListTracker> mTaskTrackers = new HashMap<>();
@@ -108,31 +108,24 @@
     }
 
     @Override
-    public void addTodoList(final ListSpec listSpec) {
+    public String addTodoList(final ListSpec listSpec) {
         final String listName = LISTS_PREFIX + mIdGenerator.generateTailId();
         final Collection listCollection = getDatabase().getCollection(getVContext(), listName);
 
-        // TODO(alexfandrianto): Syncgroup creation is slow if you specify a cloud and are offline.
-        // We'll try to connect to the cloud and then time out our RPC. The error is swallowed, so
-        // we'll just think there's a blank space of time. Maybe we should just write to these
-        // collections anyway. If https://github.com/vanadium/issues/issues/1326 is done, however,
-        // we won't need to change this code.
         Futures.addCallback(listCollection.create(getVContext(), null),
                 new SyncTrappingCallback<Void>() {
                     @Override
                     public void onSuccess(@Nullable Void result) {
-                        Futures.addCallback(createListSyncgroup(listCollection.id()),
-                                new SyncTrappingCallback<Void>() {
-                                    @Override
-                                    public void onSuccess(@Nullable Void result) {
-                                        // These can happen in either order.
-                                        trap(rememberTodoList(listName));
-                                        trap(listCollection.put(getVContext(),
-                                                SyncbaseTodoList.LIST_METADATA_ROW_NAME, listSpec));
-                                    }
-                                });
+                        // These can happen in any order.
+                        trap(listCollection.put(getVContext(),
+                                SyncbaseTodoList.LIST_METADATA_ROW_NAME, listSpec));
+                        trap(rememberTodoList(listName));
+                        // TODO(alexfandrianto): Syncgroup creation is slow if you specify a cloud
+                        // and are offline. https://github.com/vanadium/issues/issues/1326
+                        trap(createListSyncgroup(listCollection.id()));
                     }
                 });
+        return listName;
     }
 
     private ListenableFuture<SyncgroupSpec> joinListSyncgroup(String listId, String ownerBlessing) {