From 790ad839ecc85c0c3aa4a81aa3712543778e9199 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Fri, 10 Jan 2020 19:34:25 +0100 Subject: [PATCH] Awesome bar copy url (#2604) --- .../ui/widgets/SuggestionsWidget.java | 171 +++++++++++------- .../vrbrowser/ui/widgets/WindowWidget.java | 13 +- .../dialogs/SelectionActionWidget.java | 6 +- .../drawable/selection_menu_background.xml | 1 + .../selection_menu_background_triangle.xml | 12 +- .../res/layout/list_popup_window_item.xml | 12 +- 6 files changed, 124 insertions(+), 91 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/SuggestionsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/SuggestionsWidget.java index fe11962e9..7e9bce4d4 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/SuggestionsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/SuggestionsWidget.java @@ -1,7 +1,12 @@ package org.mozilla.vrbrowser.ui.widgets; +import android.content.ClipData; +import android.content.ClipboardManager; import android.content.Context; +import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Typeface; +import android.net.Uri; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.StyleSpan; @@ -12,21 +17,22 @@ import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; import androidx.annotation.NonNull; -import org.mozilla.gecko.util.ThreadUtils; +import org.mozilla.geckoview.GeckoSession; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.audio.AudioEngine; import org.mozilla.vrbrowser.ui.views.CustomListView; +import org.mozilla.vrbrowser.ui.widgets.dialogs.SelectionActionWidget; import org.mozilla.vrbrowser.utils.ViewUtils; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class SuggestionsWidget extends UIWidget implements WidgetManagerDelegate.FocusChangeListener { @@ -38,10 +44,12 @@ public class SuggestionsWidget extends UIWidget implements WidgetManagerDelegate private URLBarPopupDelegate mURLBarDelegate; private String mHighlightedText; private AudioEngine mAudio; + private ClipboardManager mClipboard; + private SelectionActionWidget mSelectionMenu; public interface URLBarPopupDelegate { - default void OnItemClicked(SuggestionItem item) {}; - default void OnItemDeleted(SuggestionItem item) {}; + default void OnItemClicked(SuggestionItem item) {} + default void OnItemLongClicked(SuggestionItem item) {} } public SuggestionsWidget(Context aContext) { @@ -87,8 +95,12 @@ public void onAnimationRepeat(Animation animation) { mAdapter = new SuggestionsAdapter(getContext(), R.layout.list_popup_window_item, new ArrayList<>()); mList.setAdapter(mAdapter); + mList.setOnItemClickListener(mClickListener); + mList.setOnItemLongClickListener(mLongClickListener); + mList.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> hideMenu()); mAudio = AudioEngine.fromContext(aContext); + mClipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); mHighlightedText = ""; } @@ -135,6 +147,7 @@ public void hideNoAnim(@HideFlags int aHideFlags) { @Override public void onGlobalFocusChanged(View oldFocus, View newFocus) { if (!ViewUtils.isEqualOrChildrenOf(this, newFocus)) { + hideMenu(); onDismiss(); } } @@ -200,7 +213,6 @@ private class ItemViewHolder { ImageView favicon; TextView title; TextView url; - ImageButton delete; View divider; } @@ -220,24 +232,18 @@ public View getView(int position, View convertView, ViewGroup parent) { itemViewHolder.layout = listItem.findViewById(R.id.layout); itemViewHolder.layout.setTag(R.string.position_tag, position); - itemViewHolder.layout.setOnClickListener(mRowListener); itemViewHolder.favicon = listItem.findViewById(R.id.favicon); itemViewHolder.title = listItem.findViewById(R.id.title); itemViewHolder.url = listItem.findViewById(R.id.url); - itemViewHolder.delete = listItem.findViewById(R.id.delete); - itemViewHolder.delete.setTag(R.string.position_tag, position); - itemViewHolder.delete.setOnClickListener(mDeleteButtonListener); itemViewHolder.divider = listItem.findViewById(R.id.divider); listItem.setTag(R.string.list_item_view_tag, itemViewHolder); listItem.setOnHoverListener(mHoverListener); - listItem.setOnTouchListener(mTouchListener); } else { itemViewHolder = (ItemViewHolder) listItem.getTag(R.string.list_item_view_tag); itemViewHolder.layout.setTag(R.string.position_tag, position); - itemViewHolder.delete.setTag(R.string.position_tag, position); } SuggestionItem selectedItem = getItem(position); @@ -274,7 +280,6 @@ public View getView(int position, View convertView, ViewGroup parent) { itemViewHolder.favicon.setImageResource(R.drawable.ic_icon_bookmark); } - itemViewHolder.delete.setVisibility(GONE); itemViewHolder.favicon.setVisibility(VISIBLE); if (position == 0) { @@ -286,59 +291,6 @@ public View getView(int position, View convertView, ViewGroup parent) { return listItem; } - OnClickListener mDeleteButtonListener = v -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } - - int position = (Integer)v.getTag(R.string.position_tag); - SuggestionItem item = getItem(position); - mAdapter.remove(item); - mAdapter.notifyDataSetChanged(); - - if (mURLBarDelegate != null) { - mURLBarDelegate.OnItemDeleted(item); - } - }; - - OnClickListener mRowListener = v -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } - - hide(KEEP_WIDGET); - - requestFocus(); - requestFocusFromTouch(); - - if (mURLBarDelegate != null) { - int position = (Integer)v.getTag(R.string.position_tag); - SuggestionItem item = getItem(position); - mURLBarDelegate.OnItemClicked(item); - } - }; - - private OnTouchListener mTouchListener = (view, event) -> { - int position = (int)view.getTag(R.string.position_tag); - if (!isEnabled(position)) { - return false; - } - - int ev = event.getActionMasked(); - switch (ev) { - case MotionEvent.ACTION_UP: - view.setPressed(false); - view.performClick(); - return true; - - case MotionEvent.ACTION_DOWN: - view.setPressed(true); - return true; - } - - return false; - }; - private OnHoverListener mHoverListener = (view, motionEvent) -> { int position = (int)view.getTag(R.string.position_tag); if (!isEnabled(position)) { @@ -348,7 +300,6 @@ public View getView(int position, View convertView, ViewGroup parent) { View favicon = view.findViewById(R.id.favicon); TextView title = view.findViewById(R.id.title); View url = view.findViewById(R.id.url); - View delete = view.findViewById(R.id.delete); int ev = motionEvent.getActionMasked(); switch (ev) { case MotionEvent.ACTION_HOVER_ENTER: @@ -357,7 +308,6 @@ public View getView(int position, View convertView, ViewGroup parent) { title.setHovered(true); title.setShadowLayer(title.getShadowRadius(), title.getShadowDx(), title.getShadowDy(), getContext().getColor(R.color.text_shadow_light)); url.setHovered(true); - delete.setHovered(true); return true; case MotionEvent.ACTION_HOVER_EXIT: @@ -366,7 +316,6 @@ public View getView(int position, View convertView, ViewGroup parent) { title.setHovered(false); title.setShadowLayer(title.getShadowRadius(), title.getShadowDx(), title.getShadowDy(), getContext().getColor(R.color.text_shadow)); url.setHovered(false); - delete.setHovered(false); return true; } @@ -374,6 +323,90 @@ public View getView(int position, View convertView, ViewGroup parent) { }; } + private AdapterView.OnItemClickListener mClickListener = new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + if (mAudio != null) { + mAudio.playSound(AudioEngine.Sound.CLICK); + } + + hide(KEEP_WIDGET); + + requestFocus(); + requestFocusFromTouch(); + + if (mURLBarDelegate != null) { + SuggestionItem item = mAdapter.getItem(position); + mURLBarDelegate.OnItemClicked(item); + } + } + }; + + private AdapterView.OnItemLongClickListener mLongClickListener = new AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + SuggestionItem item = mAdapter.getItem(position); + + view.setHovered(true); + + hideMenu(); + if (item != null) { + showMenu(view, item); + + return true; + } + + return false; + } + }; + + private void showMenu(@NonNull View view, @NonNull SuggestionItem item) { + if (mSelectionMenu == null) { + mSelectionMenu = new SelectionActionWidget(getContext()); + mSelectionMenu.mWidgetPlacement.parentHandle = getHandle(); + mSelectionMenu.setActions(Collections.singleton(GeckoSession.SelectionActionDelegate.ACTION_COPY)); + } + + Rect offsetViewBounds = new Rect(); + view.getDrawingRect(offsetViewBounds); + float ratio = WidgetPlacement.viewToWidgetRatio(getContext(), this); + offsetDescendantRectToMyCoords(view, offsetViewBounds); + RectF rectF = new RectF( + offsetViewBounds.left * ratio, + offsetViewBounds.top * ratio, + offsetViewBounds.right * ratio, + offsetViewBounds.bottom * ratio + ); + mSelectionMenu.setSelectionRect(rectF); + mSelectionMenu.setDelegate(new SelectionActionWidget.Delegate() { + @Override + public void onAction(String action) { + hideMenu(); + ClipData clip = ClipData.newRawUri(item.title, Uri.parse(item.url)); + mClipboard.setPrimaryClip(clip); + } + + @Override + public void onDismiss() { + hideMenu(); + } + }); + mSelectionMenu.show(KEEP_FOCUS); + } + + private void hideMenu() { + if (mSelectionMenu != null) { + mSelectionMenu.setDelegate((SelectionActionWidget.Delegate)null); + if (!mSelectionMenu.isReleased()) { + if (mSelectionMenu.isVisible()) { + mSelectionMenu.hide(REMOVE_WIDGET); + } + mSelectionMenu.releaseWidget(); + } + mSelectionMenu = null; + } + } + private SpannableStringBuilder createHighlightedText(@NonNull String text) { final SpannableStringBuilder sb = new SpannableStringBuilder(text); final StyleSpan bold = new StyleSpan(Typeface.BOLD); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java index fc76881d5..e97590115 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java @@ -10,6 +10,7 @@ import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.SurfaceTexture; import android.net.Uri; import android.util.Log; @@ -1726,7 +1727,17 @@ public void onShowActionRequest(@NonNull GeckoSession aSession, @NonNull Selecti Matrix matrix = new Matrix(); aSession.getClientToSurfaceMatrix(matrix); matrix.mapRect(aSelection.clientRect); - mSelectionMenu.setSelectionRect(aSelection.clientRect); + RectF selectionRect = null; + if (aSelection.clientRect != null) { + float ratio = WidgetPlacement.worldToWindowRatio(getContext()); + selectionRect = new RectF( + aSelection.clientRect.left * ratio, + aSelection.clientRect.top* ratio, + aSelection.clientRect.right * ratio, + aSelection.clientRect.bottom * ratio + ); + } + mSelectionMenu.setSelectionRect(selectionRect); mSelectionMenu.setDelegate(new SelectionActionWidget.Delegate() { @Override public void onAction(String action) { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SelectionActionWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SelectionActionWidget.java index 6bcf2fae7..5986a852f 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SelectionActionWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SelectionActionWidget.java @@ -16,11 +16,9 @@ import org.mozilla.vrbrowser.ui.widgets.UIWidget; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; -import org.mozilla.vrbrowser.utils.StringUtils; import org.mozilla.vrbrowser.utils.ViewUtils; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import static android.view.Gravity.CENTER_VERTICAL; @@ -78,8 +76,8 @@ public void show(@ShowFlags int aShowFlags) { if (mPosition != null) { mWidgetPlacement.parentAnchorX = 0.0f; mWidgetPlacement.parentAnchorY = 1.0f; - mWidgetPlacement.translationX = mPosition.x * WidgetPlacement.worldToWindowRatio(getContext()); - mWidgetPlacement.translationY = -mPosition.y * WidgetPlacement.worldToWindowRatio(getContext()); + mWidgetPlacement.translationX = mPosition.x; + mWidgetPlacement.translationY = -mPosition.y; mWidgetPlacement.translationY += mWidgetPlacement.height * 0.5f; } super.show(aShowFlags); diff --git a/app/src/main/res/drawable/selection_menu_background.xml b/app/src/main/res/drawable/selection_menu_background.xml index fab616db3..831afeb11 100644 --- a/app/src/main/res/drawable/selection_menu_background.xml +++ b/app/src/main/res/drawable/selection_menu_background.xml @@ -3,5 +3,6 @@ android:shape="rectangle"> + \ No newline at end of file diff --git a/app/src/main/res/drawable/selection_menu_background_triangle.xml b/app/src/main/res/drawable/selection_menu_background_triangle.xml index 916f45f60..3bba8c3d3 100644 --- a/app/src/main/res/drawable/selection_menu_background_triangle.xml +++ b/app/src/main/res/drawable/selection_menu_background_triangle.xml @@ -9,22 +9,22 @@ android:name="trianglegroup" android:pivotX="50" android:pivotY="50" - android:scaleX="0.95" - android:scaleY="0.95" + android:scaleX="0.92" + android:scaleY="0.92" android:translateY="-50" android:rotation="180"> + android:strokeColor="@color/iron" + android:strokeWidth="6"/> @@ -66,16 +66,6 @@ android:visibility="visible" tools:text="item URL" /> - -