Mholloway has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/380528 )

Change subject: Immediately fetch, cache page content when opening in 
background tab
......................................................................

Immediately fetch, cache page content when opening in background tab

Adds a new PageCacher class, similar to but distinct from the
SavedPageSyncService (which does more).  Exposes a static loadIntoCache
method that can be used to grab and cache all content for a page.

TODO (in a follow-up): Immediately update the tab list icons.

Bug: T168310
Change-Id: I4682f03d6993244442ba63de402d417c51ba1f70
---
M app/src/main/java/org/wikipedia/page/PageBackStackItem.java
A app/src/main/java/org/wikipedia/page/PageCacher.java
M app/src/main/java/org/wikipedia/page/PageFragment.java
3 files changed, 160 insertions(+), 7 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia 
refs/changes/28/380528/1

diff --git a/app/src/main/java/org/wikipedia/page/PageBackStackItem.java 
b/app/src/main/java/org/wikipedia/page/PageBackStackItem.java
index 80ffe3c..270cba9 100644
--- a/app/src/main/java/org/wikipedia/page/PageBackStackItem.java
+++ b/app/src/main/java/org/wikipedia/page/PageBackStackItem.java
@@ -5,21 +5,35 @@
 import org.wikipedia.history.HistoryEntry;
 import org.wikipedia.model.BaseModel;
 
+import static org.wikipedia.page.PageCacher.loadIntoCache;
+
 public class PageBackStackItem extends BaseModel {
-    private final PageTitle title;
-    @NonNull private final HistoryEntry historyEntry;
+    @NonNull private PageTitle title;
+    @NonNull private HistoryEntry historyEntry;
+
     private int scrollY;
 
     public PageBackStackItem(PageTitle title, @NonNull HistoryEntry 
historyEntry) {
-        this.title = title;
-        this.historyEntry = historyEntry;
+        this(title, historyEntry, false);
     }
 
+    public PageBackStackItem(@NonNull PageTitle title, @NonNull HistoryEntry 
entry,
+                             boolean loadPageContentOnCreate) {
+        this.title = title;
+        this.historyEntry = entry;
+
+        if (loadPageContentOnCreate) {
+            loadIntoCache(title);
+        }
+    }
+
+    @NonNull
     public PageTitle getTitle() {
         return title;
     }
 
-    @NonNull public HistoryEntry getHistoryEntry() {
+    @NonNull
+    public HistoryEntry getHistoryEntry() {
         return historyEntry;
     }
 
diff --git a/app/src/main/java/org/wikipedia/page/PageCacher.java 
b/app/src/main/java/org/wikipedia/page/PageCacher.java
new file mode 100644
index 0000000..be5a75f
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/page/PageCacher.java
@@ -0,0 +1,138 @@
+package org.wikipedia.page;
+
+import android.support.annotation.NonNull;
+
+import org.wikipedia.WikipediaApp;
+import org.wikipedia.dataclient.WikiSite;
+import org.wikipedia.dataclient.okhttp.OkHttpConnectionFactory;
+import org.wikipedia.dataclient.page.PageClient;
+import org.wikipedia.dataclient.page.PageClientFactory;
+import org.wikipedia.dataclient.page.PageLead;
+import org.wikipedia.dataclient.page.PageRemaining;
+import org.wikipedia.html.ImageTagParser;
+import org.wikipedia.html.PixelDensityDescriptorParser;
+import org.wikipedia.savedpages.PageImageUrlParser;
+import org.wikipedia.util.log.L;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+import static org.wikipedia.settings.Prefs.isImageDownloadEnabled;
+import static org.wikipedia.util.DimenUtil.calculateLeadImageWidth;
+import static org.wikipedia.util.UriUtil.resolveProtocolRelativeUrl;
+
+public final class PageCacher {
+
+    public static void loadIntoCache(@NonNull PageTitle title) {
+        L.d("Loading page into cache: " + title.getPrefixedText());
+        WikipediaApp app = WikipediaApp.getInstance();
+        PageImageUrlParser parser = new PageImageUrlParser(new 
ImageTagParser(),
+                new PixelDensityDescriptorParser());
+        PageClient client = PageClientFactory.create(title.getWikiSite(), 
title.namespace());
+        app.getSessionFunnel().leadSectionFetchStart();
+        leadReq(client, title).enqueue(new LeadCallback(title.getWikiSite(), 
parser));
+        app.getSessionFunnel().restSectionsFetchStart();
+        remainingReq(client, title).enqueue(new 
RemainingCallback(title.getWikiSite(), parser));
+    }
+
+    @NonNull
+    private static Call<PageLead> leadReq(@NonNull PageClient client, @NonNull 
PageTitle title) {
+        return client.lead(null, PageClient.CacheOption.CACHE, 
title.getPrefixedText(),
+                calculateLeadImageWidth(), !isImageDownloadEnabled());
+    }
+
+    @NonNull
+    private static Call<PageRemaining> remainingReq(@NonNull PageClient client,
+                                                    @NonNull PageTitle title) {
+        return client.sections(null, PageClient.CacheOption.CACHE, 
title.getPrefixedText(),
+                !isImageDownloadEnabled());
+    }
+
+    private static void fetchImages(@NonNull final WikiSite wiki,
+                                    @NonNull final Iterable<String> urls) {
+        OkHttpClient client = OkHttpConnectionFactory.getClient();
+        for (String url : urls) {
+            url = resolveProtocolRelativeUrl(wiki, url);
+            Request request = new Request.Builder().url(url).build();
+            client.newCall(request).enqueue(new ImageCallback());
+        }
+    }
+
+    private static final class LeadCallback implements Callback<PageLead> {
+        @NonNull private PageImageUrlParser parser;
+        @NonNull private WikiSite wiki;
+
+        private LeadCallback(@NonNull WikiSite wiki, @NonNull 
PageImageUrlParser parser) {
+            this.parser = parser;
+            this.wiki = wiki;
+        }
+
+        @Override
+        public void onResponse(@NonNull Call<PageLead> call, @NonNull 
Response<PageLead> response) {
+            
WikipediaApp.getInstance().getSessionFunnel().leadSectionFetchEnd();
+            if (response.body() != null) {
+                // noinspection ConstantConditions
+                Set<String> imageUrls = new 
HashSet<>(parser.parse(response.body()));
+                fetchImages(wiki, imageUrls);
+            }
+        }
+
+        @Override
+        public void onFailure(@NonNull Call<PageLead> call, @NonNull Throwable 
t) {
+            L.e(t);
+        }
+    }
+
+    private static final class RemainingCallback implements 
Callback<PageRemaining> {
+        @NonNull private PageImageUrlParser parser;
+        @NonNull private WikiSite wiki;
+
+        private RemainingCallback(@NonNull WikiSite wiki, @NonNull 
PageImageUrlParser parser) {
+            this.parser = parser;
+            this.wiki = wiki;
+        }
+
+        @Override
+        public void onResponse(@NonNull Call<PageRemaining> call,
+                               @NonNull Response<PageRemaining> response) {
+            
WikipediaApp.getInstance().getSessionFunnel().restSectionsFetchEnd();
+            if (response.body() != null) {
+                // noinspection ConstantConditions
+                Set<String> imageUrls = new 
HashSet<>(parser.parse(response.body()));
+                fetchImages(wiki, imageUrls);
+            }
+        }
+
+        @Override
+        public void onFailure(@NonNull Call<PageRemaining> call, @NonNull 
Throwable t) {
+            L.e(t);
+        }
+    }
+
+    private static class ImageCallback implements okhttp3.Callback {
+        @Override
+        public void onFailure(@NonNull okhttp3.Call call, @NonNull IOException 
e) {
+            L.e(e);
+        }
+
+        @Override
+        public void onResponse(@NonNull okhttp3.Call call, @NonNull 
okhttp3.Response response)
+                throws IOException {
+            // Note: raw non-Retrofit usage of OkHttp Requests requires that 
the Response body is
+            // read for the cache to be written.
+            if (response.body() != null) {
+                // noinspection ConstantConditions
+                response.body().close();
+            }
+        }
+    }
+
+    private PageCacher() { }
+}
diff --git a/app/src/main/java/org/wikipedia/page/PageFragment.java 
b/app/src/main/java/org/wikipedia/page/PageFragment.java
index d86f641..4a5d908 100755
--- a/app/src/main/java/org/wikipedia/page/PageFragment.java
+++ b/app/src/main/java/org/wikipedia/page/PageFragment.java
@@ -1053,8 +1053,9 @@
         if (shouldCreateNewTab()) {
             // create a new tab
             Tab tab = new Tab();
+            boolean isForeground = position == getForegroundTabPosition();
             // if the requested position is at the top, then make its 
backstack current
-            if (position == getForegroundTabPosition()) {
+            if (isForeground) {
                 pageFragmentLoadState.setBackStack(tab.getBackStack());
             }
             // put this tab in the requested position
@@ -1062,7 +1063,7 @@
             trimTabCount();
             tabsProvider.invalidate();
             // add the requested page to its backstack
-            tab.getBackStack().add(new PageBackStackItem(title, entry));
+            tab.getBackStack().add(new PageBackStackItem(title, entry, 
!isForeground));
             getActivity().supportInvalidateOptionsMenu();
         } else {
             getTopMostTab().getBackStack().add(new PageBackStackItem(title, 
entry));

-- 
To view, visit https://gerrit.wikimedia.org/r/380528
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I4682f03d6993244442ba63de402d417c51ba1f70
Gerrit-PatchSet: 1
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Mholloway <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to