Bug 1328937 - Extract TopSite model from stream adapter. r?grisha draft
authorSebastian Kaspari <s.kaspari@gmail.com>
Mon, 09 Jan 2017 13:53:10 +0100
changeset 457652 ab8aacb3efc846a6ba15f2a26321533a03ccccad
parent 457651 18d953c94327375c30745e29161e04d3facb0845
child 457653 9120d616b92da57ec58d738e82fdcc7db4cbc251
child 458927 dedf5b00bb167e2649c370e84c4cc53aa5429c5b
push id40848
push users.kaspari@gmail.com
push dateMon, 09 Jan 2017 13:43:11 +0000
reviewersgrisha
bugs1328937
milestone53.0a1
Bug 1328937 - Extract TopSite model from stream adapter. r?grisha MozReview-Commit-ID: IfSgvPooI9F
mobile/android/base/java/org/mozilla/gecko/activitystream/ActivityStreamTelemetry.java
mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
mobile/android/base/java/org/mozilla/gecko/home/activitystream/model/TopSite.java
mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesCard.java
mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesPageAdapter.java
mobile/android/base/moz.build
--- a/mobile/android/base/java/org/mozilla/gecko/activitystream/ActivityStreamTelemetry.java
+++ b/mobile/android/base/java/org/mozilla/gecko/activitystream/ActivityStreamTelemetry.java
@@ -139,28 +139,29 @@ public class ActivityStreamTelemetry {
                         this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_BOOKMARKED);
                         break;
                     default:
                         throw new IllegalStateException("Unknown highlight source: " + source);
                 }
                 return this;
             }
 
-            public Builder forTopSiteType(int type) {
+            public Builder forTopSiteType(@BrowserContract.TopSites.TopSiteType int type) {
                 switch (type) {
                     case BrowserContract.TopSites.TYPE_PINNED:
                         this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_PINNED);
                         break;
                     case BrowserContract.TopSites.TYPE_SUGGESTED:
                         this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_SUGGESTED);
                         break;
                     case BrowserContract.TopSites.TYPE_TOP:
                         this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_TOP);
                         break;
                     // While we also have a "blank" type, it is not used by Activity Stream.
+                    case BrowserContract.TopSites.TYPE_BLANK:
                     default:
                         throw new IllegalStateException("Unknown top site type: " + type);
                 }
                 return this;
             }
 
             public String build() {
                 return data.toString();
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.db;
 
 import org.mozilla.gecko.AppConstants;
 
 import android.net.Uri;
+import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 
 import org.mozilla.gecko.annotation.RobocopTarget;
 
 @RobocopTarget
 public class BrowserContract {
     public static final String AUTHORITY = AppConstants.ANDROID_PACKAGE_NAME + ".db.browser";
     public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
@@ -590,16 +591,19 @@ public class BrowserContract {
     public static final class TopSites implements CommonColumns, URLColumns {
         private TopSites() {}
 
         public static final int TYPE_BLANK = 0;
         public static final int TYPE_TOP = 1;
         public static final int TYPE_PINNED = 2;
         public static final int TYPE_SUGGESTED = 3;
 
+        @IntDef({TYPE_BLANK, TYPE_TOP, TYPE_PINNED, TYPE_SUGGESTED})
+        public @interface TopSiteType {}
+
         public static final String BOOKMARK_ID = "bookmark_id";
         public static final String HISTORY_ID = "history_id";
         public static final String TYPE = "type";
 
         public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "topsites");
     }
 
     public static final class Highlights {
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/home/activitystream/model/TopSite.java
@@ -0,0 +1,70 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.home.activitystream.model;
+
+import android.database.Cursor;
+import android.support.annotation.Nullable;
+
+import org.mozilla.gecko.db.BrowserContract;
+
+public class TopSite {
+    private final long id;
+    private final String url;
+    private final String title;
+    private @Nullable final Boolean isBookmarked;
+    private @BrowserContract.TopSites.TopSiteType final int type;
+
+    public static TopSite fromCursor(Cursor cursor) {
+        // The Combined View only contains pages that have been visited at least once, i.e. any
+        // page in the TopSites query will contain a HISTORY_ID. _ID however will be 0 for all rows.
+        final long id = cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Combined.HISTORY_ID));
+        final String url = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.Combined.URL));
+        final String title = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.Combined.TITLE));
+        final int type = cursor.getInt(cursor.getColumnIndexOrThrow(BrowserContract.TopSites.TYPE));
+
+        // We can't figure out bookmark state of a pin, so we leave it as unknown to be queried later.
+        Boolean isBookmarked = null;
+        if (type != BrowserContract.TopSites.TYPE_PINNED) {
+            isBookmarked = !cursor.isNull(cursor.getColumnIndexOrThrow(BrowserContract.Combined.BOOKMARK_ID));
+        }
+
+        return new TopSite(id, url, title, isBookmarked, type);
+    }
+
+    private TopSite(long id, String url, String title, @Nullable Boolean isBookmarked, int type) {
+        this.id = id;
+        this.url = url;
+        this.title = title;
+        this.isBookmarked = isBookmarked;
+        this.type = type;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    @Nullable
+    public Boolean isBookmarked() {
+        return isBookmarked;
+    }
+
+    @BrowserContract.TopSites.TopSiteType
+    public int getType() {
+        return type;
+    }
+
+    public boolean isPinned() {
+        return type == BrowserContract.TopSites.TYPE_PINNED;
+    }
+}
--- a/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesCard.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesCard.java
@@ -16,16 +16,17 @@ import android.widget.TextView;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.activitystream.ActivityStream;
 import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.home.HomePager;
 import org.mozilla.gecko.home.activitystream.menu.ActivityStreamContextMenu;
+import org.mozilla.gecko.home.activitystream.model.TopSite;
 import org.mozilla.gecko.icons.IconCallback;
 import org.mozilla.gecko.icons.IconResponse;
 import org.mozilla.gecko.icons.Icons;
 import org.mozilla.gecko.util.DrawableUtil;
 import org.mozilla.gecko.util.ViewUtil;
 import org.mozilla.gecko.util.TouchTargetUtil;
 import org.mozilla.gecko.widget.FaviconView;
 
@@ -35,19 +36,17 @@ import java.util.concurrent.Future;
 class TopSitesCard extends RecyclerView.ViewHolder
         implements IconCallback, View.OnClickListener {
     private final FaviconView faviconView;
 
     private final TextView title;
     private final ImageView menuButton;
     private Future<IconResponse> ongoingIconLoad;
 
-    private String url;
-    private int type;
-    @Nullable private Boolean isBookmarked;
+    private TopSite topSite;
 
     private final HomePager.OnUrlOpenListener onUrlOpenListener;
     private final HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener;
 
     public TopSitesCard(FrameLayout card, final HomePager.OnUrlOpenListener onUrlOpenListener, final HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener) {
         super(card);
 
         faviconView = (FaviconView) card.findViewById(R.id.favicon);
@@ -61,39 +60,37 @@ class TopSitesCard extends RecyclerView.
         card.setOnClickListener(this);
 
         TouchTargetUtil.ensureTargetHitArea(menuButton, card);
         menuButton.setOnClickListener(this);
 
         ViewUtil.enableTouchRipple(menuButton);
     }
 
-    void bind(final TopSitesPageAdapter.TopSite topSite) {
-        ActivityStream.extractLabel(itemView.getContext(), topSite.url, true, new ActivityStream.LabelCallback() {
+    void bind(final TopSite topSite) {
+        this.topSite = topSite;
+
+        ActivityStream.extractLabel(itemView.getContext(), topSite.getUrl(), true, new ActivityStream.LabelCallback() {
             @Override
             public void onLabelExtracted(String label) {
                 title.setText(label);
             }
         });
 
-        this.url = topSite.url;
-        this.type = topSite.type;
-        this.isBookmarked = topSite.isBookmarked;
-
         if (ongoingIconLoad != null) {
             ongoingIconLoad.cancel(true);
         }
 
         ongoingIconLoad = Icons.with(itemView.getContext())
-                .pageUrl(topSite.url)
+                .pageUrl(topSite.getUrl())
                 .skipNetwork()
                 .build()
                 .execute(this);
 
-        final int pinResourceId = (isPinned(this.type) ? R.drawable.pin : 0);
+        final int pinResourceId = (topSite.isPinned() ? R.drawable.pin : 0);
         TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(title, pinResourceId, 0, 0, 0);
     }
 
     @Override
     public void onIconResponse(IconResponse response) {
         faviconView.updateImage(response);
 
         final int tintColor = !response.hasColor() || response.getColor() == Color.WHITE ? Color.LTGRAY : Color.WHITE;
@@ -101,42 +98,38 @@ class TopSitesCard extends RecyclerView.
         menuButton.setImageDrawable(
                 DrawableUtil.tintDrawable(menuButton.getContext(), R.drawable.menu, tintColor));
     }
 
     @Override
     public void onClick(View clickedView) {
         ActivityStreamTelemetry.Extras.Builder extras = ActivityStreamTelemetry.Extras.builder()
                 .set(ActivityStreamTelemetry.Contract.SOURCE_TYPE, ActivityStreamTelemetry.Contract.TYPE_TOPSITES)
-                .forTopSiteType(type);
+                .forTopSiteType(topSite.getType());
 
         if (clickedView == itemView) {
-            onUrlOpenListener.onUrlOpen(url, EnumSet.noneOf(HomePager.OnUrlOpenListener.Flags.class));
+            onUrlOpenListener.onUrlOpen(topSite.getUrl(), EnumSet.noneOf(HomePager.OnUrlOpenListener.Flags.class));
 
             Telemetry.sendUIEvent(
                     TelemetryContract.Event.LOAD_URL,
                     TelemetryContract.Method.LIST_ITEM,
                     extras.build()
             );
         } else if (clickedView == menuButton) {
             ActivityStreamContextMenu.show(clickedView.getContext(),
                     menuButton,
                     extras,
                     ActivityStreamContextMenu.MenuMode.TOPSITE,
-                    title.getText().toString(), url,
+                    title.getText().toString(), topSite.getUrl(),
 
-                    isBookmarked, isPinned(type),
+                    topSite.isBookmarked(), topSite.isPinned(),
 
                     onUrlOpenListener, onUrlOpenInBackgroundListener,
                     faviconView.getWidth(), faviconView.getHeight());
 
             Telemetry.sendUIEvent(
                     TelemetryContract.Event.SHOW,
                     TelemetryContract.Method.CONTEXT_MENU,
                     extras.build()
             );
         }
     }
-
-    private boolean isPinned(int type) {
-        return type == BrowserContract.TopSites.TYPE_PINNED;
-    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesPageAdapter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesPageAdapter.java
@@ -12,37 +12,22 @@ import android.support.v7.widget.Recycle
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.home.HomePager;
+import org.mozilla.gecko.home.activitystream.model.TopSite;
 
 import java.util.ArrayList;
 import java.util.List;
 
 public class TopSitesPageAdapter extends RecyclerView.Adapter<TopSitesCard> {
-    static final class TopSite {
-        public final long id;
-        public final String url;
-        public final String title;
-        @Nullable public final Boolean isBookmarked;
-        public final int type;
-
-        TopSite(long id, String url, String title, @Nullable Boolean isBookmarked, int type) {
-            this.id = id;
-            this.url = url;
-            this.title = title;
-            this.isBookmarked = isBookmarked;
-            this.type = type;
-        }
-    }
-
     private List<TopSite> topSites;
     private int tiles;
     private int tilesWidth;
     private int tilesHeight;
     private int textHeight;
 
     private final HomePager.OnUrlOpenListener onUrlOpenListener;
     private final HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener;
@@ -57,44 +42,30 @@ public class TopSitesPageAdapter extends
         this.tilesHeight = tilesHeight;
         this.textHeight = context.getResources().getDimensionPixelSize(R.dimen.activity_stream_top_sites_text_height);
 
         this.onUrlOpenListener = onUrlOpenListener;
         this.onUrlOpenInBackgroundListener = onUrlOpenInBackgroundListener;
     }
 
     /**
-     *
-     * @param cursor
      * @param startIndex The first item that this topsites group should show. This item, and the following
      * 3 items will be displayed by this adapter.
      */
     public void swapCursor(Cursor cursor, int startIndex) {
         topSites.clear();
 
         if (cursor == null) {
             return;
         }
 
         for (int i = 0; i < tiles && startIndex + i < cursor.getCount(); i++) {
             cursor.moveToPosition(startIndex + i);
 
-            // The Combined View only contains pages that have been visited at least once, i.e. any
-            // page in the TopSites query will contain a HISTORY_ID. _ID however will be 0 for all rows.
-            final long id = cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Combined.HISTORY_ID));
-            final String url = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.Combined.URL));
-            final String title = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.Combined.TITLE));
-            final int type = cursor.getInt(cursor.getColumnIndexOrThrow(BrowserContract.TopSites.TYPE));
-
-            // We can't figure out bookmark state of a pin, so we leave it as unknown to be queried later.
-            Boolean isBookmarked = null;
-            if (type != BrowserContract.TopSites.TYPE_PINNED) {
-                isBookmarked = !cursor.isNull(cursor.getColumnIndexOrThrow(BrowserContract.Combined.BOOKMARK_ID));
-            }
-            topSites.add(new TopSite(id, url, title, isBookmarked, type));
+            topSites.add(TopSite.fromCursor(cursor));
         }
 
         notifyDataSetChanged();
     }
 
     @Override
     public void onBindViewHolder(TopSitesCard holder, int position) {
         holder.bind(topSites.get(position));
@@ -118,11 +89,11 @@ public class TopSitesPageAdapter extends
     @Override
     public int getItemCount() {
         return topSites.size();
     }
 
     @Override
     @UiThread
     public long getItemId(int position) {
-        return topSites.get(position).id;
+        return topSites.get(position).getId();
     }
 }
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -467,16 +467,17 @@ gbjar.sources += ['java/org/mozilla/geck
     'home/activitystream/ActivityStream.java',
     'home/activitystream/ActivityStreamHomeFragment.java',
     'home/activitystream/ActivityStreamHomeScreen.java',
     'home/activitystream/menu/ActivityStreamContextMenu.java',
     'home/activitystream/menu/BottomSheetContextMenu.java',
     'home/activitystream/menu/PopupContextMenu.java',
     'home/activitystream/model/Highlight.java',
     'home/activitystream/model/Metadata.java',
+    'home/activitystream/model/TopSite.java',
     'home/activitystream/stream/HighlightItem.java',
     'home/activitystream/stream/HighlightsTitle.java',
     'home/activitystream/stream/StreamItem.java',
     'home/activitystream/stream/TopPanel.java',
     'home/activitystream/stream/WelcomePanel.java',
     'home/activitystream/StreamRecyclerAdapter.java',
     'home/activitystream/topsites/CirclePageIndicator.java',
     'home/activitystream/topsites/TopSitesCard.java',