summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Miranda Kephart <mkephart@google.com> 2022-01-27 17:44:51 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-01-27 17:44:51 +0000
commitfedcd5cc381574361efb7a2e864f8ea9bfc63f7e (patch)
tree9689bc429c7509fad57118b1ebff96a17ab1dac7
parentd42cf0d4153e563629b3f18434ec10a5578159d3 (diff)
parent0a6b8a9941fd78e1873264387b6267eba1614704 (diff)
Merge "Add action chips to clipboard overlay"
-rw-r--r--packages/SystemUI/res/layout/clipboard_overlay.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java82
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java2
4 files changed, 74 insertions, 15 deletions
diff --git a/packages/SystemUI/res/layout/clipboard_overlay.xml b/packages/SystemUI/res/layout/clipboard_overlay.xml
index 7ffb3b235812..2a3761e4ca05 100644
--- a/packages/SystemUI/res/layout/clipboard_overlay.xml
+++ b/packages/SystemUI/res/layout/clipboard_overlay.xml
@@ -17,6 +17,7 @@
<com.android.systemui.clipboardoverlay.DraggableConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:alpha="0"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
index 41a496332768..0e1cd51ce42c 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
@@ -60,8 +60,8 @@ public class ClipboardListener extends CoreStartable
return;
}
if (mClipboardOverlayController == null) {
- mClipboardOverlayController = new ClipboardOverlayController(mContext,
- new TimeoutHandler(mContext));
+ mClipboardOverlayController =
+ new ClipboardOverlayController(mContext, new TimeoutHandler(mContext));
}
mClipboardOverlayController.setClipData(mClipboardManager.getPrimaryClip());
mClipboardOverlayController.setOnSessionCompleteListener(() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index caf0307d4436..b6bcb871ff18 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -28,6 +28,7 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.MainThread;
+import android.app.RemoteAction;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ComponentName;
@@ -43,6 +44,7 @@ import android.graphics.drawable.Icon;
import android.hardware.display.DisplayManager;
import android.hardware.input.InputManager;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
@@ -60,8 +62,13 @@ import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassificationManager;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextLinks;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.policy.PhoneWindow;
@@ -71,6 +78,7 @@ import com.android.systemui.screenshot.ScreenshotActionChip;
import com.android.systemui.screenshot.TimeoutHandler;
import java.io.IOException;
+import java.util.ArrayList;
/**
* Controls state and UI for the overlay that appears when something is added to the clipboard
@@ -93,6 +101,7 @@ public class ClipboardOverlayController {
private final PhoneWindow mWindow;
private final TimeoutHandler mTimeoutHandler;
private final AccessibilityManager mAccessibilityManager;
+ private final TextClassifier mTextClassifier;
private final DraggableConstraintLayout mView;
private final ImageView mImagePreview;
@@ -101,9 +110,13 @@ public class ClipboardOverlayController {
private final ScreenshotActionChip mRemoteCopyChip;
private final View mActionContainerBackground;
private final View mDismissButton;
+ private final LinearLayout mActionContainer;
+ private final ArrayList<ScreenshotActionChip> mActionChips = new ArrayList<>();
private Runnable mOnSessionCompleteListener;
+
+ private InputMonitor mInputMonitor;
private InputEventReceiver mInputEventReceiver;
private BroadcastReceiver mCloseDialogsReceiver;
@@ -117,6 +130,8 @@ public class ClipboardOverlayController {
mContext = displayContext.createWindowContext(TYPE_SCREENSHOT, null);
mAccessibilityManager = AccessibilityManager.getInstance(mContext);
+ mTextClassifier = requireNonNull(context.getSystemService(TextClassificationManager.class))
+ .getTextClassifier();
mWindowManager = mContext.getSystemService(WindowManager.class);
@@ -134,8 +149,9 @@ public class ClipboardOverlayController {
mView = (DraggableConstraintLayout)
LayoutInflater.from(mContext).inflate(R.layout.clipboard_overlay, null);
- mActionContainerBackground = requireNonNull(
- mView.findViewById(R.id.actions_container_background));
+ mActionContainerBackground =
+ requireNonNull(mView.findViewById(R.id.actions_container_background));
+ mActionContainer = requireNonNull(mView.findViewById(R.id.actions));
mImagePreview = requireNonNull(mView.findViewById(R.id.image_preview));
mTextPreview = requireNonNull(mView.findViewById(R.id.text_preview));
mEditChip = requireNonNull(mView.findViewById(R.id.edit_chip));
@@ -143,7 +159,7 @@ public class ClipboardOverlayController {
mDismissButton = requireNonNull(mView.findViewById(R.id.dismiss_button));
mView.setOnDismissCallback(this::hideImmediate);
- mView.setOnInteractionCallback(() -> mTimeoutHandler.resetTimeout());
+ mView.setOnInteractionCallback(mTimeoutHandler::resetTimeout);
mDismissButton.setOnClickListener(view -> animateOut());
@@ -166,7 +182,7 @@ public class ClipboardOverlayController {
withWindowAttached(() -> {
mWindow.setContentView(mView);
updateInsets(mWindowManager.getCurrentWindowMetrics().getWindowInsets());
- mView.post(() -> getEnterAnimation().start());
+ mView.post(this::animateIn);
});
mTimeoutHandler.setOnTimeoutRunnable(this::animateOut);
@@ -199,12 +215,15 @@ public class ClipboardOverlayController {
void setClipData(ClipData clipData) {
reset();
-
if (clipData == null || clipData.getItemCount() == 0) {
- showTextPreview(
- mContext.getResources().getString(R.string.clipboard_overlay_text_copied));
+ showTextPreview(mContext.getResources().getString(
+ R.string.clipboard_overlay_text_copied));
} else if (!TextUtils.isEmpty(clipData.getItemAt(0).getText())) {
- showEditableText(clipData.getItemAt(0).getText());
+ ClipData.Item item = clipData.getItemAt(0);
+ if (item.getTextLinks() != null) {
+ AsyncTask.execute(() -> classifyText(clipData.getItemAt(0)));
+ }
+ showEditableText(item.getText());
} else if (clipData.getItemAt(0).getUri() != null) {
// How to handle non-image URIs?
showEditableImage(clipData.getItemAt(0).getUri());
@@ -212,7 +231,6 @@ public class ClipboardOverlayController {
showTextPreview(
mContext.getResources().getString(R.string.clipboard_overlay_text_copied));
}
-
mTimeoutHandler.resetTimeout();
}
@@ -220,10 +238,40 @@ public class ClipboardOverlayController {
mOnSessionCompleteListener = runnable;
}
+ private void classifyText(ClipData.Item item) {
+ ArrayList<RemoteAction> actions = new ArrayList<>();
+ for (TextLinks.TextLink link : item.getTextLinks().getLinks()) {
+ TextClassification classification = mTextClassifier.classifyText(
+ item.getText(), link.getStart(), link.getEnd(), null);
+ actions.addAll(classification.getActions());
+ }
+ mView.post(() -> {
+ for (ScreenshotActionChip chip : mActionChips) {
+ mActionContainer.removeView(chip);
+ }
+ mActionChips.clear();
+ for (RemoteAction action : actions) {
+ ScreenshotActionChip chip = constructActionChip(action);
+ mActionContainer.addView(chip);
+ mActionChips.add(chip);
+ }
+ });
+ }
+
+ private ScreenshotActionChip constructActionChip(RemoteAction action) {
+ ScreenshotActionChip chip = (ScreenshotActionChip) LayoutInflater.from(mContext).inflate(
+ R.layout.screenshot_action_chip, mActionContainer, false);
+ chip.setText(action.getTitle());
+ chip.setIcon(action.getIcon(), false);
+ chip.setPendingIntent(action.getActionIntent(), this::animateOut);
+ chip.setAlpha(1);
+ return chip;
+ }
+
private void monitorOutsideTouches() {
InputManager inputManager = mContext.getSystemService(InputManager.class);
- InputMonitor monitor = inputManager.monitorGestureInput("clipboard overlay", 0);
- mInputEventReceiver = new InputEventReceiver(monitor.getInputChannel(),
+ mInputMonitor = inputManager.monitorGestureInput("clipboard overlay", 0);
+ mInputEventReceiver = new InputEventReceiver(mInputMonitor.getInputChannel(),
Looper.getMainLooper()) {
@Override
public void onInputEvent(InputEvent event) {
@@ -311,6 +359,10 @@ public class ClipboardOverlayController {
return nearbyIntent;
}
+ private void animateIn() {
+ getEnterAnimation().start();
+ }
+
private void animateOut() {
getExitAnimation().start();
}
@@ -390,6 +442,10 @@ public class ClipboardOverlayController {
mInputEventReceiver.dispose();
mInputEventReceiver = null;
}
+ if (mInputMonitor != null) {
+ mInputMonitor.dispose();
+ mInputMonitor = null;
+ }
if (mOnSessionCompleteListener != null) {
mOnSessionCompleteListener.run();
}
@@ -398,6 +454,10 @@ public class ClipboardOverlayController {
private void reset() {
mView.setTranslationX(0);
mView.setAlpha(0);
+ for (ScreenshotActionChip chip : mActionChips) {
+ mActionContainer.removeView(chip);
+ }
+ mActionChips.clear();
mTimeoutHandler.cancelTimeout();
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
index 6c01f0ea13a7..dec5afdaccfe 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
@@ -21,7 +21,6 @@ import android.content.Context;
import android.graphics.drawable.Icon;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -129,7 +128,6 @@ public class ScreenshotActionChip extends FrameLayout {
iconParams.setMarginStart(paddingHorizontal);
iconParams.setMarginEnd(paddingHorizontal);
}
- mTextView.setVisibility(hasText ? View.VISIBLE : View.GONE);
mIconView.setLayoutParams(iconParams);
mTextView.setLayoutParams(textParams);
}