Bug 1380808 - Add Pocket to new tab with placeholders. r=mcomella

MozReview-Commit-ID: 7yqmBF1qlLR

--HG--
rename : mobile/android/app/src/main/res/drawable/ic_as_bookmarked.xml => mobile/android/app/src/main/res/drawable/ic_as_trending.xml
rename : mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/stream/HighlightsTitleRow.java => mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/stream/StreamTitleRow.java
rename : mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/stream/HighlightItemRow.java => mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/stream/WebpageItemRow.java
extra : rebase_source : 4db18bd50d8a56201531fd464ed0cae5cebf164d
This commit is contained in:
Chenxia Liu 2017-08-17 19:05:44 -07:00
Родитель c644d4e4dc
Коммит 29f5602d05
21 изменённых файлов: 326 добавлений и 69 удалений

Просмотреть файл

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="12.0"
android:viewportHeight="12.0">
<path
android:fillColor="@color/activity_stream_icon"
android:pathData="M4.97.151l-2.819,6.5A.25.25,0,0,0,2.381,7H4.029a.25.25,0,0,1,.225.359L2,12,9.4,5.437A.25.25,0,0,0,9.234,5H6.791a.25.25,0,0,1-.19-.412L10.15.412A.25.25,0,0,0,9.959,0H5.2A.25.25,0,0,0,4.97.151Z"/>
</vector>

Просмотреть файл

@ -10,7 +10,6 @@
android:layout_marginBottom="@dimen/activity_stream_base_margin"
android:layout_marginRight="@dimen/activity_stream_base_margin"
android:layout_marginEnd="@dimen/activity_stream_base_margin"
android:text="@string/activity_stream_highlights"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"

Просмотреть файл

@ -34,6 +34,7 @@ public class ActivityStreamTelemetry {
// Values
public final static String TYPE_TOPSITES = "topsites";
public final static String TYPE_HIGHLIGHTS = "highlights";
public final static String TYPE_POCKET = "pocket";
public final static String SUBTYPE_PINNED = "pinned";
public final static String SUBTYPE_SUGGESTED = "suggested";
public final static String SUBTYPE_TOP = "top";
@ -143,6 +144,9 @@ public class ActivityStreamTelemetry {
case BOOKMARKED:
this.set(Contract.SOURCE_SUBTYPE, Contract.SUBTYPE_BOOKMARKED);
break;
case POCKET:
this.set(Contract.SOURCE_TYPE, Contract.TYPE_POCKET);
break;
default:
throw new IllegalStateException("Unknown highlight source: " + source);
}

Просмотреть файл

@ -14,7 +14,8 @@ import org.mozilla.gecko.activitystream.ranking.HighlightCandidateCursorIndices;
public class Utils {
public enum HighlightSource {
VISITED,
BOOKMARKED
BOOKMARKED,
POCKET
}
public static HighlightSource highlightSource(final Cursor cursor, final HighlightCandidateCursorIndices cursorIndices) {

Просмотреть файл

@ -17,7 +17,7 @@ import android.view.View;
* ItemDecoration implementation that draws horizontal divider line between highlight items.
*/
/* package */ class HighlightsDividerItemDecoration extends RecyclerView.ItemDecoration {
// We do not want to draw a divider for the first items: Top sites panel and highlights title.
// We do not want to draw a divider for the Top Sites panel and the Welcome panel.
private static final int START_DRAWING_AT_POSITION = 2;
private static final int[] ATTRS = new int[]{

Просмотреть файл

@ -5,7 +5,7 @@
package org.mozilla.gecko.activitystream.homepanel;
import android.support.annotation.NonNull;
import org.mozilla.gecko.activitystream.homepanel.stream.HighlightItemRow;
import org.mozilla.gecko.activitystream.homepanel.stream.WebpageItemRow;
/**
* Provides a method to open the context menu for a highlight item.
@ -14,5 +14,5 @@ import org.mozilla.gecko.activitystream.homepanel.stream.HighlightItemRow;
* (I don't understand why) so it's here instead.
*/
public interface StreamHighlightItemRowContextMenuListener {
void openContextMenu(HighlightItemRow highlightItem, int position, @NonNull final String interactionExtra);
void openContextMenu(WebpageItemRow highlightItem, int position, @NonNull final String interactionExtra);
}

Просмотреть файл

@ -13,21 +13,25 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.mozilla.gecko.R;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
import org.mozilla.gecko.activitystream.homepanel.menu.ActivityStreamContextMenu;
import org.mozilla.gecko.activitystream.homepanel.model.RowModel;
import org.mozilla.gecko.activitystream.homepanel.model.WebpageRowModel;
import org.mozilla.gecko.activitystream.homepanel.stream.TopPanelRow;
import org.mozilla.gecko.activitystream.homepanel.model.TopStory;
import org.mozilla.gecko.home.HomePager;
import org.mozilla.gecko.activitystream.homepanel.model.Highlight;
import org.mozilla.gecko.activitystream.homepanel.stream.HighlightItemRow;
import org.mozilla.gecko.activitystream.homepanel.stream.HighlightsTitleRow;
import org.mozilla.gecko.activitystream.homepanel.stream.WebpageItemRow;
import org.mozilla.gecko.activitystream.homepanel.stream.StreamTitleRow;
import org.mozilla.gecko.activitystream.homepanel.stream.StreamViewHolder;
import org.mozilla.gecko.activitystream.homepanel.stream.WelcomePanelRow;
import org.mozilla.gecko.util.StringUtils;
import org.mozilla.gecko.widget.RecyclerViewClickSupport;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
@ -44,9 +48,10 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamViewHolder
private Cursor topSitesCursor;
private List<RowModel> recyclerViewModel; // List of item types backing this RecyclerView.
private List<TopStory> topStoriesQueue;
private final RowItemType[] FIXED_ROWS = {RowItemType.TOP_PANEL, RowItemType.WELCOME, RowItemType.HIGHLIGHTS_TITLE};
private static final int HIGHLIGHTS_OFFSET = 3; // Topsites, Welcome, Highlights Title
private final RowItemType[] FIXED_ROWS = {RowItemType.TOP_PANEL, RowItemType.WELCOME, RowItemType.TOP_STORIES_TITLE, RowItemType.HIGHLIGHTS_TITLE};
private final int MAX_TOP_STORIES = 3;
private HomePager.OnUrlOpenListener onUrlOpenListener;
private HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener;
@ -57,7 +62,9 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamViewHolder
public enum RowItemType {
TOP_PANEL (-2), // RecyclerView.NO_ID is -1, so start hard-coded stableIds at -2.
WELCOME (-3),
HIGHLIGHTS_TITLE (-4),
TOP_STORIES_TITLE(-4),
TOP_STORIES_ITEM(-1), // There can be multiple Top Stories items so caller should handle as a special case.
HIGHLIGHTS_TITLE (-5),
HIGHLIGHT_ITEM (-1); // There can be multiple Highlight Items so caller should handle as a special case.
public final int stableId;
@ -86,6 +93,8 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamViewHolder
for (RowItemType type : FIXED_ROWS) {
recyclerViewModel.add(makeRowModelFromType(type));
}
topStoriesQueue = Collections.emptyList();
loadTopStories();
}
void setOnUrlOpenListeners(HomePager.OnUrlOpenListener onUrlOpenListener, HomePager.OnUrlOpenInBackgroundListener onUrlOpenInBackgroundListener) {
@ -114,19 +123,43 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamViewHolder
if (type == RowItemType.TOP_PANEL.getViewType()) {
return new TopPanelRow(inflater.inflate(TopPanelRow.LAYOUT_ID, parent, false), onUrlOpenListener, onUrlOpenInBackgroundListener);
} else if (type == RowItemType.TOP_STORIES_TITLE.getViewType()) {
return new StreamTitleRow(inflater.inflate(StreamTitleRow.LAYOUT_ID, parent, false), R.string.activity_stream_topstories);
} else if (type == RowItemType.TOP_STORIES_ITEM.getViewType()) {
return new WebpageItemRow(inflater.inflate(WebpageItemRow.LAYOUT_ID, parent, false), this);
} else if (type == RowItemType.WELCOME.getViewType()) {
return new WelcomePanelRow(inflater.inflate(WelcomePanelRow.LAYOUT_ID, parent, false), this);
} else if (type == RowItemType.HIGHLIGHT_ITEM.getViewType()) {
return new HighlightItemRow(inflater.inflate(HighlightItemRow.LAYOUT_ID, parent, false), this);
return new WebpageItemRow(inflater.inflate(WebpageItemRow.LAYOUT_ID, parent, false), this);
} else if (type == RowItemType.HIGHLIGHTS_TITLE.getViewType()) {
return new HighlightsTitleRow(inflater.inflate(HighlightsTitleRow.LAYOUT_ID, parent, false));
return new StreamTitleRow(inflater.inflate(StreamTitleRow.LAYOUT_ID, parent, false), R.string.activity_stream_highlights);
} else {
throw new IllegalStateException("Missing inflation for ViewType " + type);
}
}
private int getHighlightsOffsetFromRVPosition(int position) {
return position - HIGHLIGHTS_OFFSET;
/**
* Returns the index of an item within highlights.
* @param position position in adapter
* @return index of item within highlights
*/
private int getHighlightsIndexFromAdapterPosition(int position) {
if (getItemViewType(position) != RowItemType.HIGHLIGHT_ITEM.getViewType()) {
throw new IllegalArgumentException("Item is not a highlight!");
}
return position - indexOfType(RowItemType.HIGHLIGHT_ITEM, recyclerViewModel);
}
/**
* Returns the index of an item within top stories.
* @param position position in adapter
* @return index of item within top stories
*/
private int getTopStoriesIndexFromAdapterPosition(int position) {
if (getItemViewType(position) != RowItemType.TOP_STORIES_ITEM.getViewType()) {
throw new IllegalArgumentException("Item is not a topstory!");
}
return position - indexOfType(RowItemType.TOP_STORIES_ITEM, recyclerViewModel);
}
@Override
@ -134,25 +167,43 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamViewHolder
int type = getItemViewType(position);
if (type == RowItemType.HIGHLIGHT_ITEM.getViewType()) {
final Highlight highlight = (Highlight) recyclerViewModel.get(position);
((HighlightItemRow) holder).bind(highlight, position, tilesSize);
((WebpageItemRow) holder).bind(highlight, position, tilesSize);
} else if (type == RowItemType.TOP_PANEL.getViewType()) {
((TopPanelRow) holder).bind(topSitesCursor, tiles, tilesSize);
} else if (type == RowItemType.TOP_STORIES_ITEM.getViewType()) {
final TopStory story = (TopStory) recyclerViewModel.get(position);
((WebpageItemRow) holder).bind(story, position, tilesSize);
}
}
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
if (!onItemClickIsValidHighlightItem(position)) {
if (!onItemClickIsValidRowItem(position)) {
return;
}
final Highlight highlight = (Highlight) recyclerViewModel.get(position);
final WebpageRowModel model = (WebpageRowModel) recyclerViewModel.get(position);
final String sourceType;
final int actionPosition;
final int size;
final int viewType = getItemViewType(position);
if (viewType == RowItemType.HIGHLIGHT_ITEM.getViewType()) {
sourceType = ActivityStreamTelemetry.Contract.TYPE_HIGHLIGHTS;
actionPosition = getHighlightsIndexFromAdapterPosition(position);
size = getNumOfTypeShown(RowItemType.HIGHLIGHT_ITEM);
} else {
sourceType = ActivityStreamTelemetry.Contract.TYPE_POCKET;
actionPosition = getTopStoriesIndexFromAdapterPosition(position);
size = getNumOfTypeShown(RowItemType.TOP_STORIES_ITEM);
}
ActivityStreamTelemetry.Extras.Builder extras = ActivityStreamTelemetry.Extras.builder()
.forHighlightSource(highlight.getSource())
.set(ActivityStreamTelemetry.Contract.SOURCE_TYPE, ActivityStreamTelemetry.Contract.TYPE_HIGHLIGHTS)
.set(ActivityStreamTelemetry.Contract.ACTION_POSITION, getHighlightsOffsetFromRVPosition(position))
.set(ActivityStreamTelemetry.Contract.COUNT, recyclerViewModel.size() - FIXED_ROWS.length);
.forHighlightSource(model.getSource())
.set(ActivityStreamTelemetry.Contract.SOURCE_TYPE, sourceType)
.set(ActivityStreamTelemetry.Contract.ACTION_POSITION, actionPosition)
.set(ActivityStreamTelemetry.Contract.COUNT, size);
Telemetry.sendUIEvent(
TelemetryContract.Event.LOAD_URL,
@ -163,22 +214,24 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamViewHolder
// NB: This is hacky. We need to process telemetry data first, otherwise we run a risk of
// not having a cursor to work with once url is opened and BrowserApp closes A-S home screen
// and clears its resources (read: cursors). See Bug 1326018.
onUrlOpenListener.onUrlOpen(highlight.getUrl(), EnumSet.of(HomePager.OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
onUrlOpenListener.onUrlOpen(model.getUrl(), EnumSet.of(HomePager.OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
}
@Override
public boolean onItemLongClicked(final RecyclerView recyclerView, final int position, final View v) {
if (!onItemClickIsValidHighlightItem(position)) {
if (!onItemClickIsValidRowItem(position)) {
return false;
}
final HighlightItemRow highlightItem = (HighlightItemRow) recyclerView.getChildViewHolder(v);
final WebpageItemRow highlightItem = (WebpageItemRow) recyclerView.getChildViewHolder(v);
openContextMenu(highlightItem, position, ActivityStreamTelemetry.Contract.INTERACTION_LONG_CLICK);
return true;
}
private boolean onItemClickIsValidHighlightItem(final int position) {
if (getItemViewType(position) != RowItemType.HIGHLIGHT_ITEM.getViewType()) {
private boolean onItemClickIsValidRowItem(final int position) {
final int viewType = getItemViewType(position);
if (viewType != RowItemType.HIGHLIGHT_ITEM.getViewType()
&& viewType != RowItemType.TOP_STORIES_ITEM.getViewType()) {
// Headers (containing topsites and/or the highlights title) do their own click handling as needed
return false;
}
@ -202,23 +255,37 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamViewHolder
}
@Override
public void openContextMenu(final HighlightItemRow highlightItem, final int position, @NonNull final String interactionExtra) {
final Highlight highlight = (Highlight) recyclerViewModel.get(position);
public void openContextMenu(final WebpageItemRow webpageItemRow, final int position, @NonNull final String interactionExtra) {
final WebpageRowModel model = (WebpageRowModel) recyclerViewModel.get(position);
final String sourceType;
final int actionPosition;
final ActivityStreamContextMenu.MenuMode menuMode;
if (model.getRowItemType() == RowItemType.HIGHLIGHT_ITEM) {
sourceType = ActivityStreamTelemetry.Contract.TYPE_HIGHLIGHTS;
actionPosition = getHighlightsIndexFromAdapterPosition(position);
menuMode = ActivityStreamContextMenu.MenuMode.HIGHLIGHT;
} else {
sourceType = ActivityStreamTelemetry.Contract.TYPE_POCKET;
actionPosition = getTopStoriesIndexFromAdapterPosition(position);
menuMode = ActivityStreamContextMenu.MenuMode.TOPSTORY;
}
ActivityStreamTelemetry.Extras.Builder extras = ActivityStreamTelemetry.Extras.builder()
.set(ActivityStreamTelemetry.Contract.SOURCE_TYPE, ActivityStreamTelemetry.Contract.TYPE_HIGHLIGHTS)
.set(ActivityStreamTelemetry.Contract.ACTION_POSITION, position - HIGHLIGHTS_OFFSET)
.set(ActivityStreamTelemetry.Contract.SOURCE_TYPE, sourceType)
.set(ActivityStreamTelemetry.Contract.ACTION_POSITION, actionPosition)
.set(ActivityStreamTelemetry.Contract.INTERACTION, interactionExtra)
.forHighlightSource(highlight.getSource());
.forHighlightSource(model.getSource());
ActivityStreamContextMenu.show(highlightItem.itemView.getContext(),
highlightItem.getContextMenuAnchor(),
ActivityStreamContextMenu.show(webpageItemRow.itemView.getContext(),
webpageItemRow.getContextMenuAnchor(),
extras,
ActivityStreamContextMenu.MenuMode.HIGHLIGHT,
highlight,
menuMode,
model,
/* shouldOverrideWithImageProvider */ true, // we use image providers in HighlightItem.pageIconLayout.
onUrlOpenListener, onUrlOpenInBackgroundListener,
highlightItem.getTileWidth(), highlightItem.getTileHeight());
webpageItemRow.getTileWidth(), webpageItemRow.getTileHeight());
Telemetry.sendUIEvent(
TelemetryContract.Event.SHOW,
@ -233,11 +300,70 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamViewHolder
}
public void swapHighlights(List<Highlight> highlights) {
recyclerViewModel = recyclerViewModel.subList(0, HIGHLIGHTS_OFFSET);
recyclerViewModel = recyclerViewModel.subList(0, FIXED_ROWS.length + getNumOfTypeShown(RowItemType.TOP_STORIES_ITEM));
recyclerViewModel.addAll(highlights);
notifyDataSetChanged();
}
private void loadTopStories() {
List<TopStory> newStories = makePlaceholderStories();
topStoriesQueue = newStories;
final int insertionIndex = indexOfType(RowItemType.TOP_STORIES_TITLE, recyclerViewModel) + 1;
for (int i = 0; i < Math.min(MAX_TOP_STORIES, newStories.size()); i++) {
recyclerViewModel.add(insertionIndex + i, newStories.get(i));
}
}
/**
* Returns the index of the first item of the type found.
* @param type viewType of RowItemType
* @param rowModelList List to be indexed into
* @return index of first item of the type, or -1 if it none exist.
*/
private static int indexOfType(RowItemType type, List<RowModel> rowModelList) {
for (int i = 0; i < rowModelList.size(); i++) {
if (rowModelList.get(i).getRowItemType() == type) {
return i;
}
}
return -1;
}
/**
* Returns the number of consecutive items in the adapter of the item type specified.
*
* This is intended to be used for counting the items that have a dynamic count
* (such as Highlights or TopStory)
*
* @param type RowItemType to be counted
* @return The number of items shown.
*/
private int getNumOfTypeShown(RowItemType type) {
final int startIndex = indexOfType(type, recyclerViewModel);
if (startIndex == -1) {
return 0;
}
int count = 0;
for (int i = startIndex; i < recyclerViewModel.size(); i++) {
if (getItemViewType(i) == type.getViewType()) {
count++;
} else {
break;
}
}
return count;
}
private List<TopStory> makePlaceholderStories() {
final List<TopStory> stories = new LinkedList<>();
final String[] TITLES = { "Placeholder 1", "Placeholder 2", "Placeholder 3"};
for (String title : TITLES) {
stories.add(new TopStory(title, "https://www.mozilla.org/"));
}
return stories;
}
public void swapTopSitesCursor(Cursor cursor) {
this.topSitesCursor = cursor;
notifyItemChanged(0);
@ -246,11 +372,12 @@ public class StreamRecyclerAdapter extends RecyclerView.Adapter<StreamViewHolder
@Override
public long getItemId(int position) {
final int viewType = getItemViewType(position);
if (viewType == RowItemType.HIGHLIGHT_ITEM.getViewType()) {
if (viewType == RowItemType.HIGHLIGHT_ITEM.getViewType()
|| viewType == RowItemType.TOP_STORIES_ITEM.getViewType()) {
// Highlights are always picked from recent history - So using the history id should
// give us a unique (positive) id.
final Highlight highlight = (Highlight) recyclerViewModel.get(position);
return highlight.getHistoryId();
final WebpageRowModel model = (WebpageRowModel) recyclerViewModel.get(position);
return model.getUniqueId();
} else {
return recyclerViewModel.get(position).getRowItemType().stableId;
}

Просмотреть файл

@ -35,7 +35,8 @@ public abstract class ActivityStreamContextMenu
public enum MenuMode {
HIGHLIGHT,
TOPSITE
TOPSITE,
TOPSTORY
}
private final Context context;

Просмотреть файл

@ -18,7 +18,7 @@ import org.mozilla.gecko.activitystream.ranking.HighlightsRanking;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Highlight implements WebpageModel, RowModel {
public class Highlight implements WebpageRowModel {
/**
* A pattern matching a json object containing the key "image_url" and extracting the value. afaik, these urls
@ -214,11 +214,13 @@ public class Highlight implements WebpageModel, RowModel {
this.isPinned = pinned;
}
@Override
public Utils.HighlightSource getSource() {
return source;
}
public long getHistoryId() {
@Override
public long getUniqueId() {
return historyId;
}
}

Просмотреть файл

@ -0,0 +1,68 @@
/* -*- 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.activitystream.homepanel.model;
import org.mozilla.gecko.activitystream.Utils;
import org.mozilla.gecko.activitystream.homepanel.StreamRecyclerAdapter;
public class TopStory implements WebpageRowModel {
private final String title;
private final String url;
private final String imageUrl;
public TopStory(String title, String url) {
this(title, url, null);
}
public TopStory(String title, String url, String imageUrl) {
this.title = title;
this.url = url;
this.imageUrl = imageUrl;
}
@Override
public String getTitle() {
return title;
}
@Override
public String getUrl() {
return url;
}
@Override
public String getImageUrl() {
return imageUrl;
}
@Override
public StreamRecyclerAdapter.RowItemType getRowItemType() {
return StreamRecyclerAdapter.RowItemType.TOP_STORIES_ITEM;
}
@Override
public Boolean isBookmarked() {
return false;
}
@Override
public Boolean isPinned() {
return false;
}
public void updateBookmarked(boolean bookmarked) {}
public void updatePinned(boolean pinned) {}
@Override
public Utils.HighlightSource getSource() {
return Utils.HighlightSource.POCKET;
}
@Override
public long getUniqueId() {
return getUrl().hashCode();
}
}

Просмотреть файл

@ -0,0 +1,16 @@
/* -*- 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.activitystream.homepanel.model;
import org.mozilla.gecko.activitystream.Utils;
/**
* Model for a row in Activity Stream that represents a webpage item.
*/
public interface WebpageRowModel extends WebpageModel, RowModel {
Utils.HighlightSource getSource();
long getUniqueId();
}

Просмотреть файл

@ -5,15 +5,20 @@
package org.mozilla.gecko.activitystream.homepanel.stream;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.view.View;
import android.widget.TextView;
import org.mozilla.gecko.R;
public class HighlightsTitleRow extends StreamViewHolder {
public class StreamTitleRow extends StreamViewHolder {
public static final int LAYOUT_ID = R.layout.activity_stream_main_highlightstitle;
public HighlightsTitleRow(final View itemView) {
public StreamTitleRow(final View itemView, final @StringRes @NonNull int titleResId) {
super(itemView);
final TextView titleView = (TextView) itemView.findViewById(R.id.title_highlights);
titleView.setText(titleResId);
}
}

Просмотреть файл

@ -17,7 +17,7 @@ import org.mozilla.gecko.R;
import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
import org.mozilla.gecko.activitystream.Utils;
import org.mozilla.gecko.activitystream.homepanel.StreamHighlightItemRowContextMenuListener;
import org.mozilla.gecko.activitystream.homepanel.model.Highlight;
import org.mozilla.gecko.activitystream.homepanel.model.WebpageRowModel;
import org.mozilla.gecko.util.DrawableUtil;
import org.mozilla.gecko.util.TouchTargetUtil;
import org.mozilla.gecko.util.URIUtils;
@ -28,22 +28,23 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.util.UUID;
public class HighlightItemRow extends StreamViewHolder {
private static final String LOGTAG = "GeckoHighlightItem";
public class WebpageItemRow extends StreamViewHolder {
private static final String LOGTAG = "GeckoWebpageItemRow";
public static final int LAYOUT_ID = R.layout.activity_stream_card_history_item;
private static final double SIZE_RATIO = 0.75;
private WebpageRowModel webpageModel;
private int position;
private final StreamOverridablePageIconLayout pageIconLayout;
private final TextView pageTitleView;
private final TextView pageSourceView;
private final TextView pageDomainView;
private final TextView pageTitleView;
private final ImageView pageSourceIconView;
private final TextView pageSourceView;
private final ImageView menuButton;
public HighlightItemRow(final View itemView, final StreamHighlightItemRowContextMenuListener contextMenuListener) {
public WebpageItemRow(final View itemView, final StreamHighlightItemRowContextMenuListener contextMenuListener) {
super(itemView);
pageTitleView = (TextView) itemView.findViewById(R.id.card_history_label);
@ -60,17 +61,18 @@ public class HighlightItemRow extends StreamViewHolder {
menuButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
contextMenuListener.openContextMenu(HighlightItemRow.this, position,
contextMenuListener.openContextMenu(WebpageItemRow.this, position,
ActivityStreamTelemetry.Contract.INTERACTION_MENU_BUTTON);
}
});
}
public void bind(Highlight highlight, int position, int tilesWidth) {
public void bind(WebpageRowModel model, int position, int tilesWidth) {
this.webpageModel = model;
this.position = position;
final String backendHightlightTitle = highlight.getTitle();
final String uiHighlightTitle = !TextUtils.isEmpty(backendHightlightTitle) ? backendHightlightTitle : highlight.getUrl();
final String backendHighlightTitle = model.getTitle();
final String uiHighlightTitle = !TextUtils.isEmpty(backendHighlightTitle) ? backendHighlightTitle : model.getUrl();
pageTitleView.setText(uiHighlightTitle);
ViewGroup.LayoutParams layoutParams = pageIconLayout.getLayoutParams();
@ -78,12 +80,12 @@ public class HighlightItemRow extends StreamViewHolder {
layoutParams.height = (int) Math.floor(tilesWidth * SIZE_RATIO);
pageIconLayout.setLayoutParams(layoutParams);
updateUiForSource(highlight.getSource());
updatePageDomain(highlight);
pageIconLayout.updateIcon(highlight.getUrl(), highlight.getImageUrl());
updateUiForSource(model.getSource());
updatePageDomain();
pageIconLayout.updateIcon(model.getUrl(), model.getImageUrl());
}
private void updateUiForSource(Utils.HighlightSource source) {
public void updateUiForSource(Utils.HighlightSource source) {
switch (source) {
case BOOKMARKED:
pageSourceView.setText(R.string.activity_stream_highlight_label_bookmarked);
@ -95,6 +97,11 @@ public class HighlightItemRow extends StreamViewHolder {
pageSourceView.setVisibility(View.VISIBLE);
pageSourceIconView.setImageResource(R.drawable.ic_as_visited);
break;
case POCKET:
pageSourceView.setText(R.string.activity_stream_highlight_label_trending);
pageSourceView.setVisibility(View.VISIBLE);
pageSourceIconView.setImageResource(R.drawable.ic_as_trending);
break;
default:
pageSourceView.setVisibility(View.INVISIBLE);
pageSourceIconView.setImageResource(0);
@ -102,13 +109,13 @@ public class HighlightItemRow extends StreamViewHolder {
}
}
private void updatePageDomain(final Highlight highlight) {
private void updatePageDomain() {
final URI highlightURI;
try {
highlightURI = new URI(highlight.getUrl());
highlightURI = new URI(webpageModel.getUrl());
} catch (final URISyntaxException e) {
// If the URL is invalid, there's not much extra processing we can do on it.
pageDomainView.setText(highlight.getUrl());
pageDomainView.setText(webpageModel.getUrl());
return;
}

Просмотреть файл

@ -834,6 +834,8 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY helper_triple_readerview_open_button "Add to Bookmarks">
<!ENTITY activity_stream_topsites "Top Sites">
<!-- LOCALIZATION NOTE (activity_stream_topstories): &brandPocket is the brand of the company, Pocket, that is being used to provide suggestions for articles. -->
<!ENTITY activity_stream_topstories "Recommended by &brandPocket;">
<!ENTITY activity_stream_highlights "Highlights">
<!-- LOCALIZATION NOTE (activity_stream_highlight_label_bookmarked): This label is shown in the Activity
@ -842,6 +844,8 @@ Stream list for highlights sourced from th user's bookmarks. -->
<!-- LOCALIZATION NOTE (activity_stream_highlight_label_visited): This label is shown in the Activity
Stream list for highlights sourced from th user's bookmarks. -->
<!ENTITY activity_stream_highlight_label_visited "Visited">
<!-- LOCALIZATION NOTE (activity_stream_highlight_label_trending): This label is shown in the Activity Stream list for highlights sourced from a recommendations engine. -->
<!ENTITY activity_stream_highlight_label_trending "Trending">
<!-- LOCALIZATION NOTE (activity_stream_remove): This label is shown in the Activity Stream context menu,
and allows hiding a URL/page from highlights or topsites. The page remains in history/bookmarks, but

Просмотреть файл

@ -516,12 +516,14 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
'activitystream/homepanel/model/Metadata.java',
'activitystream/homepanel/model/RowModel.java',
'activitystream/homepanel/model/TopSite.java',
'activitystream/homepanel/model/TopStory.java',
'activitystream/homepanel/model/WebpageModel.java',
'activitystream/homepanel/stream/HighlightItemRow.java',
'activitystream/homepanel/stream/HighlightsTitleRow.java',
'activitystream/homepanel/model/WebpageRowModel.java',
'activitystream/homepanel/stream/StreamOverridablePageIconLayout.java',
'activitystream/homepanel/stream/StreamTitleRow.java',
'activitystream/homepanel/stream/StreamViewHolder.java',
'activitystream/homepanel/stream/TopPanelRow.java',
'activitystream/homepanel/stream/WebpageItemRow.java',
'activitystream/homepanel/stream/WelcomePanelRow.java',
'activitystream/homepanel/StreamHighlightItemRowContextMenuListener.java',
'activitystream/homepanel/StreamItemAnimator.java',

Просмотреть файл

@ -622,9 +622,11 @@
<string name="helper_triple_readerview_open_button">&helper_triple_readerview_open_button;</string>
<string name="activity_stream_topsites">&activity_stream_topsites;</string>
<string name="activity_stream_topstories">&activity_stream_topstories;</string>
<string name="activity_stream_highlights">&activity_stream_highlights;</string>
<string name="activity_stream_highlight_label_bookmarked">&activity_stream_highlight_label_bookmarked;</string>
<string name="activity_stream_highlight_label_visited">&activity_stream_highlight_label_visited;</string>
<string name="activity_stream_highlight_label_trending">&activity_stream_highlight_label_trending;</string>
<string name="activity_stream_remove">&activity_stream_remove;</string>
<string name="activity_stream_delete_history">&activity_stream_delete_history;</string>

Просмотреть файл

@ -4,4 +4,6 @@
<!ENTITY brandShortName "Firefox Beta">
<!ENTITY brandFullName "Mozilla Firefox Beta">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY brandPocket "Pocket">

Просмотреть файл

@ -4,4 +4,6 @@
<!ENTITY brandShortName "Nightly">
<!ENTITY brandFullName "Mozilla Nightly">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY brandPocket "Pocket">

Просмотреть файл

@ -4,4 +4,6 @@
<!ENTITY brandShortName "Nightly">
<!ENTITY brandFullName "Mozilla Nightly">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY brandPocket "Pocket">

Просмотреть файл

@ -4,4 +4,6 @@
<!ENTITY brandShortName "Firefox">
<!ENTITY brandFullName "Mozilla Firefox">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY brandPocket "Pocket">

Просмотреть файл

@ -4,4 +4,6 @@
<!ENTITY brandShortName "Fennec">
<!ENTITY brandFullName "Mozilla Fennec">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY brandPocket "Pocket">