Skip to content

Commit

Permalink
Awesome bar copy url (#2604)
Browse files Browse the repository at this point in the history
  • Loading branch information
keianhzo authored and bluemarvin committed Jan 10, 2020
1 parent 970212e commit 790ad83
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 91 deletions.
@@ -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;
Expand All @@ -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 {
Expand All @@ -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) {
Expand Down Expand Up @@ -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 = "";
}
Expand Down Expand Up @@ -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();
}
}
Expand Down Expand Up @@ -200,7 +213,6 @@ private class ItemViewHolder {
ImageView favicon;
TextView title;
TextView url;
ImageButton delete;
View divider;
}

Expand All @@ -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);
Expand Down Expand Up @@ -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) {
Expand All @@ -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)) {
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -366,14 +316,97 @@ 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;
}

return false;
};
}

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);
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/drawable/selection_menu_background.xml
Expand Up @@ -3,5 +3,6 @@
android:shape="rectangle">
<corners android:radius="20dp" />
<stroke android:color="@color/asphalt_blur" android:width="@dimen/blur_radius" />
<stroke android:color="@color/iron" android:width="2dp"/>
<solid android:color="@color/asphalt"/>
</shape>
12 changes: 6 additions & 6 deletions app/src/main/res/drawable/selection_menu_background_triangle.xml
Expand Up @@ -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">
<path
android:name="triangle2"
android:pathData="M 50 0 L 100 50 L 0 50 Z"
android:strokeColor="@color/asphalt_blur"
android:strokeWidth="4"/>
android:strokeColor="@color/iron"
android:strokeWidth="6"/>
</group>
<group
android:name="trianglegroup2"
android:pivotX="50"
android:pivotY="50"
android:scaleX="0.90"
android:scaleY="0.90"
android:scaleX="0.85"
android:scaleY="0.85"
android:translateY="-50"
android:rotation="180">
<path
Expand Down

0 comments on commit 790ad83

Please sign in to comment.