reader/android: determine the initial page automatically.

When a device joins an existing device set, it determines the initial
page to show based on what the other devices in the device set are
currently looking at. More specifically, the initial page becomes the
last page of the first consecutive set of pages + 1.

Ex1) When there is only one device looking at page 2: the initial page
of the second device is determined 3.

Ex2) Two devices are looking at pages 3 and 4: the initial page of the
third device is 5.

Ex3) Two devices are looking at pages 3 and 5: the initial page of the
third device is 4.

Closes #53.

Change-Id: Ib52bff8efb37cd7798200df1221dbd1b8c91d5a1
diff --git a/android/app/src/main/java/io/v/android/apps/reader/PdfViewWrapper.java b/android/app/src/main/java/io/v/android/apps/reader/PdfViewWrapper.java
index e02c5a6..831dd3b 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/PdfViewWrapper.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/PdfViewWrapper.java
@@ -37,7 +37,7 @@
     /**
      * Loads the PDF file at the given path into the pdf.js component within WebView.
      */
-    public void loadPdfFile(final String fileId) throws IOException {
+    public void loadPdfFile(final String fileId, final int initialPage) throws IOException {
         File pdfFile = new File(getContext().getCacheDir(), fileId);
 
         try (InputStream in = DB.Singleton.get(getContext()).getInputStreamForFile(fileId);
@@ -48,7 +48,7 @@
         mRenderer = new PdfRenderer(
                 ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY));
 
-        setPage(1);
+        setPage(initialPage);
     }
 
     /**
diff --git a/android/app/src/main/java/io/v/android/apps/reader/PdfViewerActivity.java b/android/app/src/main/java/io/v/android/apps/reader/PdfViewerActivity.java
index df59143..ad48a0d 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/PdfViewerActivity.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/PdfViewerActivity.java
@@ -34,6 +34,7 @@
 import io.v.android.apps.reader.vdl.DeviceSet;
 import io.v.android.apps.reader.vdl.File;
 import io.v.v23.verror.VException;
+import java8.util.stream.StreamSupport;
 
 /**
  * Activity that shows the contents of the selected pdf file.
@@ -166,7 +167,10 @@
 
             // Get the device set from the DB and join it.
             DeviceSet ds = mDeviceSets.getItemById(intent.getStringExtra(EXTRA_DEVICE_SET_ID));
-            joinDeviceSet(ds);
+
+            // Use the post method to join the device set
+            // only after the initial view layout is performed.
+            mPdfView.post(() -> joinDeviceSet(ds));
         } else if (intent.getData() != null) {
             /**
              * Case #2.
@@ -274,8 +278,8 @@
         getDB().updateDeviceSet(mCurrentDS);
     }
 
-    private DeviceMeta createDeviceMeta() {
-        int page = 1;
+    private DeviceMeta createDeviceMeta(int initialPage) {
+        int page = initialPage;
         int zoom = 1;
         boolean linked = true;
 
@@ -296,17 +300,28 @@
     private void joinDeviceSet(DeviceSet ds) {
         showProgressWidgets(false);
 
+        Log.i(TAG, "Joining device set: " + ds.getId());
+
+        // Get the last page number of the first consecutive set of pages in the device set.
+        int lastPage = StreamSupport.stream(ds.getDevices().values())
+                .map(DeviceMeta::getPage)
+                .sorted()
+                .reduce((x, y) -> (y - x) > 1 ? x : y)
+                .orElse(0);
+
+        // Create a new device meta, and update the device set with it.
+        // Set the initial page as lastPage + 1.
+        DeviceMeta dm = createDeviceMeta(lastPage + 1);
+
+        // Load the pdf file.
         try {
-            mPdfView.loadPdfFile(ds.getFileId());
+            mPdfView.loadPdfFile(ds.getFileId(), dm.getPage());
         } catch(IOException e) {
             handleException(e);
             finish();
             return;
         }
 
-        // Create a new device meta, and update the device set with it.
-        Log.i(TAG, "Joining device set: " + ds.getId());
-        DeviceMeta dm = createDeviceMeta();
         // TODO(youngseokyoon): don't wait till these operations are finished.
         ds.getDevices().put(dm.getDeviceId(), dm);
         getDB().updateDeviceSet(ds);