reader/android: show active device sets instead of pdf files

This CL changes the PdfChooserActivity to DeviceSetChooserActivity,
which means that the first screen the user sees shows the list of
currently active device sets.

A device set always has a file attached to it, and when the user
clicks on a device set, the app shows the content of the corresponding
PDF file.

Change-Id: I6e840ac267482aee52b0bc2f2997edfef1eefeb5
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index cda8c5f..2c258f7 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -8,7 +8,7 @@
         android:label="@string/app_name"
         android:theme="@style/AppTheme">
         <activity
-            android:name=".PdfChooserActivity"
+            android:name=".DeviceSetChooserActivity"
             android:label="@string/app_name">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/android/app/src/main/java/io/v/android/apps/reader/PdfChooserActivity.java b/android/app/src/main/java/io/v/android/apps/reader/DeviceSetChooserActivity.java
similarity index 76%
rename from android/app/src/main/java/io/v/android/apps/reader/PdfChooserActivity.java
rename to android/app/src/main/java/io/v/android/apps/reader/DeviceSetChooserActivity.java
index be53c5b..14c040d 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/PdfChooserActivity.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/DeviceSetChooserActivity.java
@@ -16,15 +16,15 @@
 import io.v.android.apps.reader.db.DB;
 
 /**
- * Activity that displays all the available pdf files in a list.
+ * Activity that displays all the active device sets of this user.
  *
- * When the user clicks on one of the pdf files, it starts the PdfViewerActivity with the
- * corresponding file.
+ * When the user clicks on one of the device sets, it starts the PdfViewerActivity with the file
+ * associated with the device set.
  */
-public class PdfChooserActivity extends Activity {
+public class DeviceSetChooserActivity extends Activity {
 
     private RecyclerView mRecyclerView;
-    private PdfListAdapter mAdapter;
+    private DeviceSetListAdapter mAdapter;
     private DB mDB;
 
     protected void onCreate(Bundle savedInstanceState) {
@@ -34,9 +34,9 @@
         mDB = DB.Singleton.get(this);
         mDB.init(this);
 
-        setContentView(R.layout.activity_pdf_chooser);
+        setContentView(R.layout.activity_device_set_chooser);
 
-        mRecyclerView = (RecyclerView) findViewById(R.id.pdf_list);
+        mRecyclerView = (RecyclerView) findViewById(R.id.device_set_list);
         mRecyclerView.setHasFixedSize(true);
 
         // Use the linear layout manager for the recycler view
@@ -49,15 +49,15 @@
         super.onStart();
 
         // The adapter for the recycler view
-        mAdapter = new PdfListAdapter(this);
+        mAdapter = new DeviceSetListAdapter(this);
 
         // When a file is clicked from the list, start the PdfViewerActivity.
-        mAdapter.setOnPdfFileClickListener(new PdfListAdapter.OnPdfFileClickListener() {
+        mAdapter.setOnDeviceSetClickListener(new DeviceSetListAdapter.OnDeviceSetClickListener() {
             @Override
-            public void onPdfFileClick(PdfListAdapter adapter, View v, int position) {
+            public void onDeviceSetClick(DeviceSetListAdapter adapter, View v, int position) {
                 Intent intent = PdfViewerActivity.createIntent(
                         getApplicationContext(),
-                        adapter.getItem(position));
+                        adapter.getItemTitle(position));
                 startActivity(intent);
             }
         });
@@ -78,7 +78,7 @@
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         // Inflate the menu; this adds items to the action bar if it is present.
-        getMenuInflater().inflate(R.menu.menu_pdf_chooser, menu);
+        getMenuInflater().inflate(R.menu.menu_device_set_chooser, menu);
         return true;
     }
 
diff --git a/android/app/src/main/java/io/v/android/apps/reader/DeviceSetListAdapter.java b/android/app/src/main/java/io/v/android/apps/reader/DeviceSetListAdapter.java
new file mode 100644
index 0000000..9002e93
--- /dev/null
+++ b/android/app/src/main/java/io/v/android/apps/reader/DeviceSetListAdapter.java
@@ -0,0 +1,105 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.android.apps.reader;
+
+import android.content.Context;
+import android.support.v7.widget.CardView;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import io.v.android.apps.reader.db.DB;
+import io.v.android.apps.reader.db.DB.DBList;
+import io.v.android.apps.reader.model.Listener;
+import io.v.android.apps.reader.vdl.DeviceSet;
+import io.v.android.apps.reader.vdl.File;
+
+/**
+ * Adapter that binds the list of device sets to the corresponding card views.
+ */
+public class DeviceSetListAdapter extends RecyclerView.Adapter<DeviceSetListAdapter.ViewHolder>
+        implements Listener {
+
+    private OnDeviceSetClickListener mClickListener;
+    private DB mDB;
+    private DBList<DeviceSet> mDeviceSets;
+
+    public class ViewHolder extends RecyclerView.ViewHolder {
+        public CardView mCardView;
+        public TextView mTextView;
+
+        public ViewHolder(CardView v) {
+            super(v);
+            mCardView = v;
+            mTextView = (TextView) mCardView.findViewById(R.id.device_set_list_item_text);
+
+            mCardView.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (mClickListener != null) {
+                        mClickListener.onDeviceSetClick(DeviceSetListAdapter.this, v, getPosition());
+                    }
+                }
+            });
+        }
+    }
+
+    public DeviceSetListAdapter(Context context) {
+        mClickListener = null;
+
+        mDB = DB.Singleton.get(context);
+        mDeviceSets = mDB.getDeviceSetList();
+        mDeviceSets.setListener(this);
+    }
+
+    @Override
+    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        // Create a new view here.
+        CardView v = (CardView) LayoutInflater.from(parent.getContext())
+                .inflate(R.layout.device_set_list_item, parent, false);
+
+        return new ViewHolder(v);
+    }
+
+    @Override
+    public void onBindViewHolder(ViewHolder holder, int position) {
+        holder.mTextView.setText(getItemTitle(position));
+    }
+
+    public String getItemTitle(int position) {
+        DeviceSet ds = mDeviceSets.getItem(position);
+        File file = mDB.getFileById(ds.getFileId());
+
+        if (file != null) {
+            return file.getTitle();
+        } else {
+            return "*** Error retrieving the file name";
+        }
+    }
+
+    @Override
+    public int getItemCount() {
+        return mDeviceSets.getItemCount();
+    }
+
+    public void setOnDeviceSetClickListener(OnDeviceSetClickListener clickListener) {
+        mClickListener = clickListener;
+    }
+
+    public void stop() {
+        mDeviceSets.discard();
+        mDeviceSets = null;
+    }
+
+    /**
+     * Interface used for handling click events of the pdf files in the list.
+     */
+    public interface OnDeviceSetClickListener {
+        void onDeviceSetClick(DeviceSetListAdapter adapter, View v, int position);
+    }
+
+}
diff --git a/android/app/src/main/java/io/v/android/apps/reader/PdfListAdapter.java b/android/app/src/main/java/io/v/android/apps/reader/PdfListAdapter.java
deleted file mode 100644
index ee19389..0000000
--- a/android/app/src/main/java/io/v/android/apps/reader/PdfListAdapter.java
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2015 The Vanadium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package io.v.android.apps.reader;
-
-import android.content.Context;
-import android.support.v7.widget.CardView;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import io.v.android.apps.reader.db.DB;
-import io.v.android.apps.reader.db.DB.DBList;
-import io.v.android.apps.reader.model.Listener;
-import io.v.android.apps.reader.vdl.File;
-
-/**
- * Adapter that binds the list of pdf files to the corresponding card views.
- */
-public class PdfListAdapter extends RecyclerView.Adapter<PdfListAdapter.ViewHolder>
-        implements Listener {
-
-    private OnPdfFileClickListener mClickListener;
-    private DBList<File> mPdfFileList;
-
-    public class ViewHolder extends RecyclerView.ViewHolder {
-        public CardView mCardView;
-        public TextView mTextView;
-
-        public ViewHolder(CardView v) {
-            super(v);
-            mCardView = v;
-            mTextView = (TextView) mCardView.findViewById(R.id.pdf_list_item_text);
-
-            mCardView.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    if (mClickListener != null) {
-                        mClickListener.onPdfFileClick(PdfListAdapter.this, v, getPosition());
-                    }
-                }
-            });
-        }
-    }
-
-    public PdfListAdapter(Context context) {
-        mClickListener = null;
-
-        DB db = DB.Singleton.get(context);
-        mPdfFileList = db.getFileList();
-        mPdfFileList.setListener(this);
-    }
-
-    @Override
-    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-        // Create a new view here.
-        CardView v = (CardView) LayoutInflater.from(parent.getContext())
-                .inflate(R.layout.pdf_list_item, parent, false);
-
-        return new ViewHolder(v);
-    }
-
-    @Override
-    public void onBindViewHolder(ViewHolder holder, int position) {
-        holder.mTextView.setText(getItem(position));
-    }
-
-    public String getItem(int position) {
-        return mPdfFileList.getItem(position).getTitle();
-    }
-
-    @Override
-    public int getItemCount() {
-        return mPdfFileList.getItemCount();
-    }
-
-    public void setOnPdfFileClickListener(OnPdfFileClickListener clickListener) {
-        mClickListener = clickListener;
-    }
-
-    public void stop() {
-        mPdfFileList.discard();
-        mPdfFileList = null;
-    }
-
-    /**
-     * Interface used for handling click events of the pdf files in the list.
-     */
-    public interface OnPdfFileClickListener {
-        void onPdfFileClick(PdfListAdapter adapter, View v, int position);
-    }
-
-}
diff --git a/android/app/src/main/java/io/v/android/apps/reader/db/DB.java b/android/app/src/main/java/io/v/android/apps/reader/db/DB.java
index 4b19874..87cdeab 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/db/DB.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/db/DB.java
@@ -9,6 +9,7 @@
 import android.content.Intent;
 
 import io.v.android.apps.reader.model.Listener;
+import io.v.android.apps.reader.vdl.DeviceSet;
 import io.v.android.apps.reader.vdl.File;
 
 /**
@@ -88,4 +89,17 @@
      */
     DBList<File> getFileList();
 
+    /**
+     * Gets the list of currently active device sets.
+     * @return a list of device sets.
+     */
+    DBList<DeviceSet> getDeviceSetList();
+
+    /**
+     * Gets the PDF file with the given id.
+     * @param id the id of the file
+     * @return the file object, or null if there is no file with the given id.
+     */
+    File getFileById(String id);
+
 }
diff --git a/android/app/src/main/java/io/v/android/apps/reader/db/FakeDB.java b/android/app/src/main/java/io/v/android/apps/reader/db/FakeDB.java
index 642f2de..8d4e4e8 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/db/FakeDB.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/db/FakeDB.java
@@ -12,6 +12,7 @@
 import java.util.List;
 
 import io.v.android.apps.reader.model.Listener;
+import io.v.android.apps.reader.vdl.DeviceSet;
 import io.v.android.apps.reader.vdl.File;
 
 /**
@@ -19,15 +20,22 @@
  */
 public class FakeDB implements DB {
 
-    private static final String[] FILE_NAMES = {
-            "Foo.pdf",
-            "Bar.pdf"
+    private static final Object[][] FILE_DATA = {
+            { "fileId1", "Foo.pdf" },
+            { "fileId2", "Bar.pdf" },
+    };
+
+    private static final Object[][] DEVICE_SET_DATA = {
+            { "deviceSetId1", "fileId1" },
+            { "deviceSetId2", "fileId2" },
     };
 
     private FakeFileList mFileList;
+    private FakeDeviceSetList mDeviceSetList;
 
     public FakeDB(Context context) {
         mFileList = new FakeFileList();
+        mDeviceSetList = new FakeDeviceSetList();
     }
 
     static class FakeFileList implements DBList<File> {
@@ -37,13 +45,19 @@
 
         public FakeFileList() {
             mFiles = new ArrayList<>();
-            for (String fileName : FILE_NAMES) {
-                mFiles.add(createFile(fileName));
+            for (Object[] fileData : FILE_DATA) {
+                mFiles.add(createFile(fileData));
             }
         }
 
-        private static File createFile(String title) {
-            return new File(null, null, title, 0L, null);
+        private static File createFile(Object[] fileData) {
+            return new File(
+                    (String) fileData[0],   // File ID
+                    null,                   // BlobRef
+                    (String) fileData[1],   // Title
+                    0L,                     // Size
+                    null                    // Type
+            );
         }
 
         @Override
@@ -70,6 +84,50 @@
         }
     }
 
+    static class FakeDeviceSetList implements DBList<DeviceSet> {
+
+        private List<DeviceSet> mDeviceSets;
+        private Listener mListener;
+
+        public FakeDeviceSetList() {
+            mDeviceSets = new ArrayList<>();
+            for (Object[] deviceSetData : DEVICE_SET_DATA) {
+                mDeviceSets.add(createDeviceSet(deviceSetData));
+            }
+        }
+
+        private static DeviceSet createDeviceSet(Object[] deviceSetData) {
+            return new DeviceSet(
+                    (String) deviceSetData[0],  // Device Set ID
+                    (String) deviceSetData[1],  // File ID
+                    null                        // Devices
+            );
+        }
+
+        @Override
+        public int getItemCount() {
+            return mDeviceSets.size();
+        }
+
+        @Override
+        public DeviceSet getItem(int position) {
+            return mDeviceSets.get(position);
+        }
+
+        @Override
+        public void setListener(Listener listener) {
+            // This fake list never calls the notify methods.
+            // Just check if the listener is set only once.
+            assert mListener == null;
+            mListener = listener;
+        }
+
+        @Override
+        public void discard() {
+            // Nothing to do.
+        }
+    }
+
     public void init(Activity activity) {
         // Nothing to do.
     }
@@ -85,4 +143,21 @@
         return mFileList;
     }
 
+    @Override
+    public DBList<DeviceSet> getDeviceSetList() {
+        return mDeviceSetList;
+    }
+
+    @Override
+    public File getFileById(String id) {
+        for (int i = 0; i < mFileList.getItemCount(); ++i) {
+            File file = mFileList.getItem(i);
+            if (file.getId().equals(id)) {
+                return file;
+            }
+        }
+
+        return null;
+    }
+
 }
diff --git a/android/app/src/main/java/io/v/android/apps/reader/db/SyncbaseDB.java b/android/app/src/main/java/io/v/android/apps/reader/db/SyncbaseDB.java
index f0c5ccf..c72045c 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/db/SyncbaseDB.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/db/SyncbaseDB.java
@@ -14,6 +14,7 @@
 import com.google.common.collect.ImmutableMap;
 
 import io.v.android.apps.reader.model.Listener;
+import io.v.android.apps.reader.vdl.DeviceSet;
 import io.v.android.apps.reader.vdl.File;
 import io.v.android.libs.security.BlessingsManager;
 import io.v.android.v23.V;
@@ -187,14 +188,14 @@
     }
 
     // TODO(youngseokyoon): Remove once the list is implemented properly.
-    private static class EmptyFileList implements DBList<File> {
+    private static class EmptyList<E> implements DBList<E> {
         @Override
         public int getItemCount() {
             return 0;
         }
 
         @Override
-        public File getItem(int position) {
+        public E getItem(int position) {
             return null;
         }
 
@@ -209,7 +210,17 @@
 
     @Override
     public DBList<File> getFileList() {
-        return new EmptyFileList();
+        return new EmptyList<File>();
+    }
+
+    @Override
+    public DBList<DeviceSet> getDeviceSetList() {
+        return new EmptyList<DeviceSet>();
+    }
+
+    @Override
+    public File getFileById(String id) {
+        return null;
     }
 
     private void handleError(String msg) {
diff --git a/android/app/src/main/res/layout/activity_pdf_chooser.xml b/android/app/src/main/res/layout/activity_device_set_chooser.xml
similarity index 85%
rename from android/app/src/main/res/layout/activity_pdf_chooser.xml
rename to android/app/src/main/res/layout/activity_device_set_chooser.xml
index dced51b..4a18c57 100644
--- a/android/app/src/main/res/layout/activity_pdf_chooser.xml
+++ b/android/app/src/main/res/layout/activity_device_set_chooser.xml
@@ -1,13 +1,13 @@
 <android.support.v7.widget.RecyclerView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/pdf_list"
+    android:id="@+id/device_set_list"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingBottom="@dimen/activity_vertical_margin"
     android:paddingLeft="@dimen/activity_horizontal_margin"
     android:paddingRight="@dimen/activity_horizontal_margin"
     android:paddingTop="@dimen/activity_vertical_margin"
-    tools:context=".PdfChooserActivity">
+    tools:context=".DeviceSetChooserActivity">
 
 </android.support.v7.widget.RecyclerView>
diff --git a/android/app/src/main/res/layout/activity_pdf_viewer.xml b/android/app/src/main/res/layout/activity_pdf_viewer.xml
index c1410a6..9f57074 100644
--- a/android/app/src/main/res/layout/activity_pdf_viewer.xml
+++ b/android/app/src/main/res/layout/activity_pdf_viewer.xml
@@ -9,7 +9,7 @@
     android:layout_marginLeft="@dimen/activity_horizontal_margin"
     android:layout_marginRight="@dimen/activity_horizontal_margin"
     android:layout_marginTop="@dimen/activity_vertical_margin"
-    tools:context=".PdfChooserActivity">
+    tools:context=".PdfViewerActivity">
 
     <Button
         android:id="@+id/button_prev"
diff --git a/android/app/src/main/res/layout/device_set_list_item.xml b/android/app/src/main/res/layout/device_set_list_item.xml
new file mode 100644
index 0000000..851c899
--- /dev/null
+++ b/android/app/src/main/res/layout/device_set_list_item.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/device_set_list_item"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_marginBottom="@dimen/device_set_list_vertical_margin"
+    android:layout_marginLeft="@dimen/device_set_list_horizontal_margin"
+    android:layout_marginRight="@dimen/device_set_list_horizontal_margin"
+    android:layout_marginTop="@dimen/device_set_list_vertical_margin"
+    android:scrollbars="vertical">
+
+    <TextView
+        android:id="@+id/device_set_list_item_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="@dimen/device_set_list_item_vertical_margin"
+        android:layout_marginLeft="@dimen/device_set_list_item_horizontal_margin"
+        android:layout_marginRight="@dimen/device_set_list_item_horizontal_margin"
+        android:layout_marginTop="@dimen/device_set_list_item_vertical_margin"/>
+
+</android.support.v7.widget.CardView>
diff --git a/android/app/src/main/res/layout/pdf_list_item.xml b/android/app/src/main/res/layout/pdf_list_item.xml
deleted file mode 100644
index af6f2ba..0000000
--- a/android/app/src/main/res/layout/pdf_list_item.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/pdf_list_item"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginBottom="@dimen/pdf_list_vertical_margin"
-    android:layout_marginLeft="@dimen/pdf_list_horizontal_margin"
-    android:layout_marginRight="@dimen/pdf_list_horizontal_margin"
-    android:layout_marginTop="@dimen/pdf_list_vertical_margin"
-    android:scrollbars="vertical">
-
-    <TextView
-        android:id="@+id/pdf_list_item_text"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/pdf_list_item_vertical_margin"
-        android:layout_marginLeft="@dimen/pdf_list_item_horizontal_margin"
-        android:layout_marginRight="@dimen/pdf_list_item_horizontal_margin"
-        android:layout_marginTop="@dimen/pdf_list_item_vertical_margin"/>
-
-</android.support.v7.widget.CardView>
diff --git a/android/app/src/main/res/menu/menu_pdf_chooser.xml b/android/app/src/main/res/menu/menu_device_set_chooser.xml
similarity index 86%
rename from android/app/src/main/res/menu/menu_pdf_chooser.xml
rename to android/app/src/main/res/menu/menu_device_set_chooser.xml
index ff5de99..60fca2e 100644
--- a/android/app/src/main/res/menu/menu_pdf_chooser.xml
+++ b/android/app/src/main/res/menu/menu_device_set_chooser.xml
@@ -1,6 +1,6 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
-    tools:context=".PdfChooserActivity">
+    tools:context=".DeviceSetChooserActivity">
     <item
         android:id="@+id/action_settings"
         android:orderInCategory="100"
diff --git a/android/app/src/main/res/values/dimens.xml b/android/app/src/main/res/values/dimens.xml
index b05b7d8..65f95b3 100644
--- a/android/app/src/main/res/values/dimens.xml
+++ b/android/app/src/main/res/values/dimens.xml
@@ -3,9 +3,9 @@
     <dimen name="activity_horizontal_margin">16dp</dimen>
     <dimen name="activity_vertical_margin">16dp</dimen>
 
-    <dimen name="pdf_list_horizontal_margin">4dp</dimen>
-    <dimen name="pdf_list_vertical_margin">4dp</dimen>
+    <dimen name="device_set_list_horizontal_margin">4dp</dimen>
+    <dimen name="device_set_list_vertical_margin">4dp</dimen>
 
-    <dimen name="pdf_list_item_horizontal_margin">16dp</dimen>
-    <dimen name="pdf_list_item_vertical_margin">16dp</dimen>
+    <dimen name="device_set_list_item_horizontal_margin">16dp</dimen>
+    <dimen name="device_set_list_item_vertical_margin">16dp</dimen>
 </resources>