Commit 55b83c1f authored by Brandon Wylie's avatar Brandon Wylie Committed by Commit Bot

[Touchless][EoS] Add to My apps context menu item

Adds the context menu and the code for the homescreen shortcut.

Bug: 955514
Change-Id: I851059a23d1283340e453f1a2f00280cebd93142
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1589375
Commit-Queue: Brandon Wylie <wylieb@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Reviewed-by: default avatarCathy Li <chili@chromium.org>
Reviewed-by: default avatarJustin DeWitt <dewittj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#656491}
parent e18b691d
...@@ -614,7 +614,6 @@ chrome_java_sources = [ ...@@ -614,7 +614,6 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java", "java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java",
"java/src/org/chromium/chrome/browser/explore_sites/CategoryCardAdapter.java", "java/src/org/chromium/chrome/browser/explore_sites/CategoryCardAdapter.java",
"java/src/org/chromium/chrome/browser/explore_sites/CategoryCardViewHolderFactory.java", "java/src/org/chromium/chrome/browser/explore_sites/CategoryCardViewHolderFactory.java",
"java/src/org/chromium/chrome/browser/explore_sites/CondensedCategoryCardViewHolderFactory.java",
"java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesCategoryTileView.java", "java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesCategoryTileView.java",
"java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesSection.java", "java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesSection.java",
"java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTask.java", "java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTask.java",
......
...@@ -377,18 +377,6 @@ ...@@ -377,18 +377,6 @@
<dimen name="explore_sites_loading_spinny_size">36dp</dimen> <dimen name="explore_sites_loading_spinny_size">36dp</dimen>
<dimen name="explore_sites_loading_spinny_padding">24dp</dimen> <dimen name="explore_sites_loading_spinny_padding">24dp</dimen>
<dimen name="explore_sites_category_padding_vertical_condensed">12dp</dimen>
<dimen name="explore_sites_category_padding_horizontal_condensed">4dp</dimen>
<dimen name="explore_sites_category_grid_minimum_spacing">8dp</dimen>
<dimen name="explore_sites_category_title_spacing_condensed">10dp</dimen>
<dimen name="explore_sites_tile_view_icon_background_size_condensed">44dp</dimen>
<dimen name="explore_sites_tile_view_icon_size_condensed">22dp</dimen>
<dimen name="explore_sites_tile_view_icon_margin_top_condensed">18dp</dimen>
<dimen name="explore_sites_tile_view_title_margin_top_condensed">51dp</dimen>
<dimen name="explore_sites_tile_view_width_condensed">72dp</dimen>
<dimen name="explore_sites_tile_view_icon_padding_horizontal_condensed">4dp</dimen>
<dimen name="explore_sites_tile_view_text_margin_bottom_condensed">4dp</dimen>
<!-- Recent tabs page --> <!-- Recent tabs page -->
<dimen name="recent_tabs_visible_separator_padding">8dp</dimen> <dimen name="recent_tabs_visible_separator_padding">8dp</dimen>
<dimen name="recent_tabs_group_view_vertical_padding">8dp</dimen> <dimen name="recent_tabs_group_view_vertical_padding">8dp</dimen>
......
...@@ -232,7 +232,7 @@ public class ShortcutHelper { ...@@ -232,7 +232,7 @@ public class ShortcutHelper {
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
@CalledByNative @CalledByNative
private static void addShortcut(String id, String url, String userTitle, Bitmap icon, public static void addShortcut(String id, String url, String userTitle, Bitmap icon,
boolean isIconAdaptive, int source) { boolean isIconAdaptive, int source) {
Context context = ContextUtils.getApplicationContext(); Context context = ContextUtils.getApplicationContext();
final Intent shortcutIntent = createShortcutIntent(url); final Intent shortcutIntent = createShortcutIntent(url);
......
...@@ -13,7 +13,7 @@ import org.chromium.chrome.R; ...@@ -13,7 +13,7 @@ import org.chromium.chrome.R;
import org.chromium.ui.modelutil.RecyclerViewAdapter; import org.chromium.ui.modelutil.RecyclerViewAdapter;
/** Factory to create CategoryCardViewHolder objects. */ /** Factory to create CategoryCardViewHolder objects. */
class CategoryCardViewHolderFactory implements RecyclerViewAdapter.ViewHolderFactory< public class CategoryCardViewHolderFactory implements RecyclerViewAdapter.ViewHolderFactory<
CategoryCardViewHolderFactory.CategoryCardViewHolder> { CategoryCardViewHolderFactory.CategoryCardViewHolder> {
/** View holder for the recycler view. */ /** View holder for the recycler view. */
public static class CategoryCardViewHolder extends RecyclerView.ViewHolder { public static class CategoryCardViewHolder extends RecyclerView.ViewHolder {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.explore_sites; package org.chromium.chrome.browser.explore_sites;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Rect; import android.graphics.Rect;
...@@ -70,13 +71,13 @@ public class ExploreSitesCategoryCardView extends LinearLayout { ...@@ -70,13 +71,13 @@ public class ExploreSitesCategoryCardView extends LinearLayout {
mTileViewLayout = tileResource; mTileViewLayout = tileResource;
} }
private class CategoryCardInteractionDelegate protected class CategoryCardInteractionDelegate
implements ContextMenuManager.Delegate, OnClickListener, OnCreateContextMenuListener, implements ContextMenuManager.Delegate, OnClickListener, OnCreateContextMenuListener,
OnFocusChangeListener { OnFocusChangeListener {
private String mSiteUrl; private String mSiteUrl;
private int mTileIndex; private int mTileIndex;
CategoryCardInteractionDelegate(String siteUrl, int tileIndex) { public CategoryCardInteractionDelegate(String siteUrl, int tileIndex) {
mSiteUrl = siteUrl; mSiteUrl = siteUrl;
mTileIndex = tileIndex; mTileIndex = tileIndex;
} }
...@@ -146,7 +147,7 @@ public class ExploreSitesCategoryCardView extends LinearLayout { ...@@ -146,7 +147,7 @@ public class ExploreSitesCategoryCardView extends LinearLayout {
// paradigm for the category card view itself since it is mismatched to the needs of the // paradigm for the category card view itself since it is mismatched to the needs of the
// recycler view that we use for category cards. The controller for MVC is actually here, the // recycler view that we use for category cards. The controller for MVC is actually here, the
// bind code inside the view class. // bind code inside the view class.
private class ExploreSitesSiteViewBinder protected class ExploreSitesSiteViewBinder
implements PropertyModelChangeProcessor implements PropertyModelChangeProcessor
.ViewBinder<PropertyModel, ExploreSitesTileView, PropertyKey> { .ViewBinder<PropertyModel, ExploreSitesTileView, PropertyKey> {
@Override @Override
...@@ -159,14 +160,18 @@ public class ExploreSitesCategoryCardView extends LinearLayout { ...@@ -159,14 +160,18 @@ public class ExploreSitesCategoryCardView extends LinearLayout {
} else if (key == ExploreSitesSite.URL_KEY) { } else if (key == ExploreSitesSite.URL_KEY) {
// Attach click handlers. // Attach click handlers.
CategoryCardInteractionDelegate interactionDelegate = CategoryCardInteractionDelegate interactionDelegate =
new CategoryCardInteractionDelegate(model.get(ExploreSitesSite.URL_KEY), createInteractionDelegate(model);
model.get(ExploreSitesSite.TILE_INDEX_KEY));
view.setOnClickListener(interactionDelegate); view.setOnClickListener(interactionDelegate);
view.setOnCreateContextMenuListener(interactionDelegate); view.setOnCreateContextMenuListener(interactionDelegate);
ContextMenuManager.registerViewForTouchlessContextMenu(view, interactionDelegate); ContextMenuManager.registerViewForTouchlessContextMenu(view, interactionDelegate);
view.setOnFocusChangeListener(interactionDelegate); view.setOnFocusChangeListener(interactionDelegate);
} }
} }
protected CategoryCardInteractionDelegate createInteractionDelegate(PropertyModel model) {
return new CategoryCardInteractionDelegate(model.get(ExploreSitesSite.URL_KEY),
model.get(ExploreSitesSite.TILE_INDEX_KEY));
}
} }
public ExploreSitesCategoryCardView(Context context, AttributeSet attrs) { public ExploreSitesCategoryCardView(Context context, AttributeSet attrs) {
...@@ -245,7 +250,7 @@ public class ExploreSitesCategoryCardView extends LinearLayout { ...@@ -245,7 +250,7 @@ public class ExploreSitesCategoryCardView extends LinearLayout {
siteModel.set(ExploreSitesSite.TILE_INDEX_KEY, tileIndex); siteModel.set(ExploreSitesSite.TILE_INDEX_KEY, tileIndex);
mModelChangeProcessors.add(PropertyModelChangeProcessor.create( mModelChangeProcessors.add(PropertyModelChangeProcessor.create(
siteModel, tileView, new ExploreSitesSiteViewBinder())); siteModel, tileView, createViewBinder((Activity) getContext())));
// Fetch icon if not present already. // Fetch icon if not present already.
if (siteModel.get(ExploreSitesSite.ICON_KEY) == null) { if (siteModel.get(ExploreSitesSite.ICON_KEY) == null) {
...@@ -276,4 +281,8 @@ public class ExploreSitesCategoryCardView extends LinearLayout { ...@@ -276,4 +281,8 @@ public class ExploreSitesCategoryCardView extends LinearLayout {
RecordHistogram.recordLinearCountHistogram("ExploreSites.SiteTilesClickIndex", RecordHistogram.recordLinearCountHistogram("ExploreSites.SiteTilesClickIndex",
cardIndex * MAX_TILE_COUNT + tileIndex, 1, 100, 100); cardIndex * MAX_TILE_COUNT + tileIndex, 1, 100, 100);
} }
protected ExploreSitesSiteViewBinder createViewBinder(Activity activity) {
return new ExploreSitesSiteViewBinder();
}
} }
...@@ -31,7 +31,6 @@ import org.chromium.chrome.browser.profiles.Profile; ...@@ -31,7 +31,6 @@ import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tab.TabObserver;
import org.chromium.chrome.browser.util.FeatureUtilities;
import org.chromium.chrome.browser.widget.RoundedIconGenerator; import org.chromium.chrome.browser.widget.RoundedIconGenerator;
import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.NavigationController;
import org.chromium.content_public.browser.NavigationEntry; import org.chromium.content_public.browser.NavigationEntry;
...@@ -162,9 +161,7 @@ public class ExploreSitesPage extends BasicNativePage { ...@@ -162,9 +161,7 @@ public class ExploreSitesPage extends BasicNativePage {
mView.setNavigationDelegate(host.createHistoryNavigationDelegate()); mView.setNavigationDelegate(host.createHistoryNavigationDelegate());
mRecyclerView = mView.findViewById(R.id.explore_sites_category_recycler); mRecyclerView = mView.findViewById(R.id.explore_sites_category_recycler);
CategoryCardViewHolderFactory factory = FeatureUtilities.isNoTouchModeEnabled() CategoryCardViewHolderFactory factory = createCategoryCardViewHolderFactory();
? new CondensedCategoryCardViewHolderFactory()
: new CategoryCardViewHolderFactory();
RecyclerViewAdapter<CategoryCardViewHolderFactory.CategoryCardViewHolder, Void> adapter = RecyclerViewAdapter<CategoryCardViewHolderFactory.CategoryCardViewHolder, Void> adapter =
new RecyclerViewAdapter<>(adapterDelegate, factory); new RecyclerViewAdapter<>(adapterDelegate, factory);
...@@ -375,4 +372,8 @@ public class ExploreSitesPage extends BasicNativePage { ...@@ -375,4 +372,8 @@ public class ExploreSitesPage extends BasicNativePage {
return RecyclerView.NO_POSITION; return RecyclerView.NO_POSITION;
} }
protected CategoryCardViewHolderFactory createCategoryCardViewHolderFactory() {
return new CategoryCardViewHolderFactory();
}
} }
...@@ -16,13 +16,13 @@ public class ExploreSitesSite { ...@@ -16,13 +16,13 @@ public class ExploreSitesSite {
static final int DEFAULT_TILE_INDEX = -1; static final int DEFAULT_TILE_INDEX = -1;
static final PropertyModel.ReadableIntPropertyKey ID_KEY = static final PropertyModel.ReadableIntPropertyKey ID_KEY =
new PropertyModel.ReadableIntPropertyKey(); new PropertyModel.ReadableIntPropertyKey();
static final PropertyModel.WritableIntPropertyKey TILE_INDEX_KEY = public static final PropertyModel.WritableIntPropertyKey TILE_INDEX_KEY =
new PropertyModel.WritableIntPropertyKey(); new PropertyModel.WritableIntPropertyKey();
static final PropertyModel.ReadableObjectPropertyKey<String> TITLE_KEY = public static final PropertyModel.ReadableObjectPropertyKey<String> TITLE_KEY =
new PropertyModel.ReadableObjectPropertyKey<>(); new PropertyModel.ReadableObjectPropertyKey<>();
static final PropertyModel.ReadableObjectPropertyKey<String> URL_KEY = public static final PropertyModel.ReadableObjectPropertyKey<String> URL_KEY =
new PropertyModel.ReadableObjectPropertyKey<>(); new PropertyModel.ReadableObjectPropertyKey<>();
static final PropertyModel.WritableObjectPropertyKey<Bitmap> ICON_KEY = public static final PropertyModel.WritableObjectPropertyKey<Bitmap> ICON_KEY =
new PropertyModel.WritableObjectPropertyKey<>(); new PropertyModel.WritableObjectPropertyKey<>();
static final PropertyModel.WritableBooleanPropertyKey BLACKLISTED_KEY = static final PropertyModel.WritableBooleanPropertyKey BLACKLISTED_KEY =
new PropertyModel.WritableBooleanPropertyKey(); new PropertyModel.WritableBooleanPropertyKey();
......
...@@ -33,7 +33,8 @@ import java.lang.annotation.RetentionPolicy; ...@@ -33,7 +33,8 @@ import java.lang.annotation.RetentionPolicy;
public class ContextMenuManager implements OnCloseContextMenuListener { public class ContextMenuManager implements OnCloseContextMenuListener {
@IntDef({ContextMenuItemId.OPEN_IN_NEW_WINDOW, ContextMenuItemId.OPEN_IN_NEW_TAB, @IntDef({ContextMenuItemId.OPEN_IN_NEW_WINDOW, ContextMenuItemId.OPEN_IN_NEW_TAB,
ContextMenuItemId.OPEN_IN_INCOGNITO_TAB, ContextMenuItemId.SAVE_FOR_OFFLINE, ContextMenuItemId.OPEN_IN_INCOGNITO_TAB, ContextMenuItemId.SAVE_FOR_OFFLINE,
ContextMenuItemId.REMOVE, ContextMenuItemId.LEARN_MORE}) ContextMenuItemId.ADD_TO_MY_APPS, ContextMenuItemId.REMOVE,
ContextMenuItemId.LEARN_MORE})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface ContextMenuItemId { public @interface ContextMenuItemId {
// The order of the items will be based on the value of their ID. So if new items are added, // The order of the items will be based on the value of their ID. So if new items are added,
...@@ -43,10 +44,11 @@ public class ContextMenuManager implements OnCloseContextMenuListener { ...@@ -43,10 +44,11 @@ public class ContextMenuManager implements OnCloseContextMenuListener {
int OPEN_IN_NEW_TAB = 1; int OPEN_IN_NEW_TAB = 1;
int OPEN_IN_INCOGNITO_TAB = 2; int OPEN_IN_INCOGNITO_TAB = 2;
int SAVE_FOR_OFFLINE = 3; int SAVE_FOR_OFFLINE = 3;
int REMOVE = 4; int ADD_TO_MY_APPS = 4;
int LEARN_MORE = 5; int REMOVE = 5;
int LEARN_MORE = 6;
int NUM_ENTRIES = 6; int NUM_ENTRIES = 7;
} }
private final NativePageNavigationDelegate mNavigationDelegate; private final NativePageNavigationDelegate mNavigationDelegate;
...@@ -206,6 +208,8 @@ public class ContextMenuManager implements OnCloseContextMenuListener { ...@@ -206,6 +208,8 @@ public class ContextMenuManager implements OnCloseContextMenuListener {
return true; return true;
case ContextMenuItemId.LEARN_MORE: case ContextMenuItemId.LEARN_MORE:
return true; return true;
case ContextMenuItemId.ADD_TO_MY_APPS:
return false;
default: default:
assert false; assert false;
return false; return false;
......
<!-- Copyright 2019 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
tools:targetApi="21">
<path
android:fillColor="@color/default_icon_color"
android:pathData="M13,7h-2v4L7,11v2h4v4h2v-4h4v-2h-4L13,7zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
</vector>
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
Use of this source code is governed by a BSD-style license that can be Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. --> found in the LICENSE file. -->
<org.chromium.chrome.browser.explore_sites.ExploreSitesCategoryCardView <org.chromium.chrome.browser.touchless.TouchlessExploreSitesCategoryCardView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
...@@ -35,4 +35,4 @@ ...@@ -35,4 +35,4 @@
app:minHorizontalSpacing="@dimen/explore_sites_category_grid_minimum_spacing" app:minHorizontalSpacing="@dimen/explore_sites_category_grid_minimum_spacing"
android:paddingTop="@dimen/explore_sites_category_title_spacing_condensed" /> android:paddingTop="@dimen/explore_sites_category_title_spacing_condensed" />
</org.chromium.chrome.browser.explore_sites.ExploreSitesCategoryCardView> </org.chromium.chrome.browser.touchless.TouchlessExploreSitesCategoryCardView>
...@@ -54,4 +54,16 @@ ...@@ -54,4 +54,16 @@
the mocks don't take into account --> the mocks don't take into account -->
<dimen name="touchless_snippets_age_margin_bottom">10dp</dimen> <dimen name="touchless_snippets_age_margin_bottom">10dp</dimen>
<dimen name="explore_sites_category_padding_vertical_condensed">12dp</dimen>
<dimen name="explore_sites_category_padding_horizontal_condensed">4dp</dimen>
<dimen name="explore_sites_category_grid_minimum_spacing">8dp</dimen>
<dimen name="explore_sites_category_title_spacing_condensed">10dp</dimen>
<dimen name="explore_sites_tile_view_icon_background_size_condensed">44dp</dimen>
<dimen name="explore_sites_tile_view_icon_size_condensed">22dp</dimen>
<dimen name="explore_sites_tile_view_icon_margin_top_condensed">18dp</dimen>
<dimen name="explore_sites_tile_view_title_margin_top_condensed">51dp</dimen>
<dimen name="explore_sites_tile_view_width_condensed">72dp</dimen>
<dimen name="explore_sites_tile_view_icon_padding_horizontal_condensed">4dp</dimen>
<dimen name="explore_sites_tile_view_text_margin_bottom_condensed">4dp</dimen>
</resources> </resources>
// Copyright 2019 The Chromium 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 org.chromium.chrome.browser.touchless;
import android.app.Activity;
import android.graphics.Bitmap;
import org.chromium.chrome.browser.ShortcutHelper;
import org.chromium.chrome.browser.webapps.AddToHomescreenDialog;
/**
* Add to homescreen manager specifically for touchless devices.
*/
class TouchlessAddToHomescreenManager implements AddToHomescreenDialog.Delegate {
protected final Activity mActivity;
private final String mUrl;
private final String mTitle;
private final Bitmap mIconBitmap;
protected AddToHomescreenDialog mDialog;
public TouchlessAddToHomescreenManager(
Activity activity, String url, String title, Bitmap iconBitmap) {
mActivity = activity;
mUrl = url;
mTitle = title;
mIconBitmap = iconBitmap;
}
// Starts the process of showing the dialog and adding the shortcut.
public void start() {
mDialog = new AddToHomescreenDialog(mActivity, this);
mDialog.show();
mDialog.onUserTitleAvailable(mTitle, mUrl, false);
mDialog.onIconAvailable(mIconBitmap);
}
@Override
public void addToHomescreen(String title) {
ShortcutHelper.addShortcut(mUrl, mUrl, title, mIconBitmap, false, 0);
}
@Override
public void onNativeAppDetailsRequested() {
return;
}
@Override
public void onDialogDismissed() {
mDialog = null;
}
}
...@@ -2,22 +2,22 @@ ...@@ -2,22 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
package org.chromium.chrome.browser.explore_sites; package org.chromium.chrome.browser.touchless;
import org.chromium.chrome.R; import org.chromium.chrome.browser.explore_sites.CategoryCardViewHolderFactory;
import org.chromium.chrome.touchless.R;
class CondensedCategoryCardViewHolderFactory extends CategoryCardViewHolderFactory {
public CondensedCategoryCardViewHolderFactory() {
super();
}
/**
* Factory to provide resources for touchless devices.
*/
class TouchlessCategoryCardViewHolderFactory extends CategoryCardViewHolderFactory {
@Override @Override
protected int getCategoryCardViewResource() { protected int getCategoryCardViewResource() {
return R.layout.explore_sites_category_card_view_condensed; return R.layout.touchless_explore_sites_category_card_view;
} }
@Override @Override
protected int getTileViewResource() { protected int getTileViewResource() {
return R.layout.explore_sites_tile_view_condensed; return R.layout.touchless_explore_sites_tile_view_condensed;
} }
} }
...@@ -4,8 +4,11 @@ ...@@ -4,8 +4,11 @@
package org.chromium.chrome.browser.touchless; package org.chromium.chrome.browser.touchless;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
...@@ -26,6 +29,26 @@ import java.util.ArrayList; ...@@ -26,6 +29,26 @@ import java.util.ArrayList;
* ContextMenuManager and Delegate to select items to show and lookup their labels. * ContextMenuManager and Delegate to select items to show and lookup their labels.
*/ */
public class TouchlessContextMenuManager extends ContextMenuManager { public class TouchlessContextMenuManager extends ContextMenuManager {
/**
* Delegate for touchless-specific context menu items.
*/
public interface Delegate extends ContextMenuManager.Delegate {
/**
* @return Activity associated with this delegate. Used to display prompts.
*/
Activity getActivity();
/**
* @return Title associated with this delegate.
*/
String getTitle();
/**
* @return Icon associated with this delegate. Used to populate touchless shortcuts.
*/
Bitmap getIconBitmap();
}
private PropertyModel mTouchlessMenuModel; private PropertyModel mTouchlessMenuModel;
private ModalDialogManager mModalDialogManager; private ModalDialogManager mModalDialogManager;
...@@ -43,8 +66,8 @@ public class TouchlessContextMenuManager extends ContextMenuManager { ...@@ -43,8 +66,8 @@ public class TouchlessContextMenuManager extends ContextMenuManager {
* @param delegate Delegate defines filter for displayed menu items and behavior for selects * @param delegate Delegate defines filter for displayed menu items and behavior for selects
* item. * item.
*/ */
public void showTouchlessContextMenu( public void showTouchlessContextMenu(ModalDialogManager modalDialogManager, Context context,
ModalDialogManager modalDialogManager, Context context, Delegate delegate) { ContextMenuManager.Delegate delegate) {
ArrayList<PropertyModel> menuItems = new ArrayList(); ArrayList<PropertyModel> menuItems = new ArrayList();
for (@ContextMenuItemId int itemId = 0; itemId < ContextMenuItemId.NUM_ENTRIES; itemId++) { for (@ContextMenuItemId int itemId = 0; itemId < ContextMenuItemId.NUM_ENTRIES; itemId++) {
if (!shouldShowItem(itemId, delegate)) continue; if (!shouldShowItem(itemId, delegate)) continue;
...@@ -68,7 +91,32 @@ public class TouchlessContextMenuManager extends ContextMenuManager { ...@@ -68,7 +91,32 @@ public class TouchlessContextMenuManager extends ContextMenuManager {
} }
@Override @Override
protected boolean shouldShowItem(@ContextMenuItemId int itemId, Delegate delegate) { protected @StringRes int getResourceIdForMenuItem(@ContextMenuItemId int id) {
if (id == ContextMenuItemId.ADD_TO_MY_APPS) {
return R.string.menu_add_to_apps;
}
return super.getResourceIdForMenuItem(id);
}
@Override
protected boolean handleMenuItemClick(
@ContextMenuItemId int itemId, ContextMenuManager.Delegate delegate) {
if (itemId == ContextMenuItemId.ADD_TO_MY_APPS) {
Delegate touchlessDelegate = (Delegate) delegate;
TouchlessAddToHomescreenManager touchlessAddToHomescreenManager =
new TouchlessAddToHomescreenManager(touchlessDelegate.getActivity(),
touchlessDelegate.getUrl(), touchlessDelegate.getTitle(),
touchlessDelegate.getIconBitmap());
touchlessAddToHomescreenManager.start();
return false;
}
return super.handleMenuItemClick(itemId, delegate);
}
@Override
protected boolean shouldShowItem(
@ContextMenuItemId int itemId, ContextMenuManager.Delegate delegate) {
// Here we filter out any item IDs that don't make sense in touchless. // Here we filter out any item IDs that don't make sense in touchless.
switch (itemId) { switch (itemId) {
case ContextMenuItemId.REMOVE: case ContextMenuItemId.REMOVE:
...@@ -83,6 +131,8 @@ public class TouchlessContextMenuManager extends ContextMenuManager { ...@@ -83,6 +131,8 @@ public class TouchlessContextMenuManager extends ContextMenuManager {
// fall through // fall through
case ContextMenuItemId.OPEN_IN_NEW_WINDOW: case ContextMenuItemId.OPEN_IN_NEW_WINDOW:
return false; return false;
case ContextMenuItemId.ADD_TO_MY_APPS:
return delegate.isItemSupported(itemId);
} }
assert false : "Encountered unexpected touchless context menu item type"; assert false : "Encountered unexpected touchless context menu item type";
...@@ -139,6 +189,8 @@ public class TouchlessContextMenuManager extends ContextMenuManager { ...@@ -139,6 +189,8 @@ public class TouchlessContextMenuManager extends ContextMenuManager {
return R.drawable.ic_remove_circle_outline_24dp; return R.drawable.ic_remove_circle_outline_24dp;
case ContextMenuItemId.LEARN_MORE: case ContextMenuItemId.LEARN_MORE:
return R.drawable.ic_help_outline_24dp; return R.drawable.ic_help_outline_24dp;
case ContextMenuItemId.ADD_TO_MY_APPS:
return R.drawable.ic_add_circle_outline_24dp;
default: default:
return 0; return 0;
} }
...@@ -149,10 +201,11 @@ public class TouchlessContextMenuManager extends ContextMenuManager { ...@@ -149,10 +201,11 @@ public class TouchlessContextMenuManager extends ContextMenuManager {
} }
private class TouchlessItemClickListener implements OnClickListener { private class TouchlessItemClickListener implements OnClickListener {
private final Delegate mDelegate; private final ContextMenuManager.Delegate mDelegate;
private final @ContextMenuItemId int mItemId; private final @ContextMenuItemId int mItemId;
public TouchlessItemClickListener(Delegate delegate, @ContextMenuItemId int itemId) { public TouchlessItemClickListener(
ContextMenuManager.Delegate delegate, @ContextMenuItemId int itemId) {
mDelegate = delegate; mDelegate = delegate;
mItemId = itemId; mItemId = itemId;
} }
......
// Copyright 2019 The Chromium 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 org.chromium.chrome.browser.touchless;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.AttributeSet;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.explore_sites.ExploreSitesCategoryCardView;
import org.chromium.chrome.browser.explore_sites.ExploreSitesSite;
import org.chromium.chrome.browser.native_page.ContextMenuManager;
import org.chromium.ui.modelutil.PropertyModel;
class TouchlessExploreSitesCategoryCardView extends ExploreSitesCategoryCardView {
public TouchlessExploreSitesCategoryCardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected class TouchlessExploreSitesSiteViewBinder
extends ExploreSitesCategoryCardView.ExploreSitesSiteViewBinder {
Activity mActivity;
public TouchlessExploreSitesSiteViewBinder(Activity activity) {
mActivity = activity;
}
@Override
protected ExploreSitesCategoryCardView.CategoryCardInteractionDelegate
createInteractionDelegate(PropertyModel model) {
return new TouchlessCategoryCardInteractionDelegate((ChromeActivity) mActivity, model);
}
}
/**
* Delegate that's aware of fields necessary for the touchless context menu.
*/
protected class TouchlessCategoryCardInteractionDelegate
extends ExploreSitesCategoryCardView.CategoryCardInteractionDelegate
implements TouchlessContextMenuManager.Delegate {
private ChromeActivity mActivity;
private PropertyModel mModel;
TouchlessCategoryCardInteractionDelegate(ChromeActivity activity, PropertyModel model) {
super(model.get(ExploreSitesSite.URL_KEY), model.get(ExploreSitesSite.TILE_INDEX_KEY));
mActivity = activity;
mModel = model;
}
@Override
public Activity getActivity() {
return mActivity;
}
@Override
public String getTitle() {
return mModel.get(ExploreSitesSite.TITLE_KEY);
}
@Override
public Bitmap getIconBitmap() {
return mModel.get(ExploreSitesSite.ICON_KEY);
}
@Override
public boolean isItemSupported(int menuItemId) {
return menuItemId == ContextMenuManager.ContextMenuItemId.ADD_TO_MY_APPS
|| menuItemId == ContextMenuManager.ContextMenuItemId.REMOVE;
}
}
@Override
protected ExploreSitesSiteViewBinder createViewBinder(Activity activity) {
return new TouchlessExploreSitesSiteViewBinder(activity);
}
}
...@@ -8,6 +8,7 @@ import android.content.Context; ...@@ -8,6 +8,7 @@ import android.content.Context;
import android.view.View; import android.view.View;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.explore_sites.CategoryCardViewHolderFactory;
import org.chromium.chrome.browser.explore_sites.ExploreSitesPage; import org.chromium.chrome.browser.explore_sites.ExploreSitesPage;
import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.native_page.ContextMenuManager;
import org.chromium.chrome.browser.native_page.NativePageHost; import org.chromium.chrome.browser.native_page.NativePageHost;
...@@ -49,4 +50,9 @@ public class TouchlessExploreSitesPage extends ExploreSitesPage { ...@@ -49,4 +50,9 @@ public class TouchlessExploreSitesPage extends ExploreSitesPage {
mTouchlessContextMenuManager.showTouchlessContextMenu( mTouchlessContextMenuManager.showTouchlessContextMenu(
mModalDialogManager, mContext, delegate); mModalDialogManager, mContext, delegate);
} }
@Override
protected CategoryCardViewHolderFactory createCategoryCardViewHolderFactory() {
return new TouchlessCategoryCardViewHolderFactory();
}
} }
...@@ -131,6 +131,10 @@ ...@@ -131,6 +131,10 @@
<message name="IDS_MORE_ARTICLES" desc="Message at the bottom of a list of news items prompting the user to load more."> <message name="IDS_MORE_ARTICLES" desc="Message at the bottom of a list of news items prompting the user to load more.">
More articles More articles
</message> </message>
<!-- TODO(crbug.com/957789): Remove this from downstream. -->
<message name="IDS_MENU_ADD_TO_APPS" desc="Text to accompany icon that will navigate to a page showing a categorized view of different applications or sites">
Add to My apps
</message>
</messages> </messages>
</release> </release>
</grit> </grit>
...@@ -24,10 +24,13 @@ touchless_java_sources = [ ...@@ -24,10 +24,13 @@ touchless_java_sources = [
"touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsRecyclerView.java", "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsRecyclerView.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java", "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsViewHolderFactory.java", "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsViewHolderFactory.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessAddToHomescreenManager.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolder.java", "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolder.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessArticleViewHolder.java", "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessArticleViewHolder.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessCategoryCardViewHolderFactory.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessContextMenuManager.java", "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessContextMenuManager.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java", "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesCategoryCardView.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesPage.java", "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesPage.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessLayoutManager.java", "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessLayoutManager.java",
"touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java", "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment