OSDN Git Service

Improved the experience when sending multiple messages
authorSelim Cinek <cinek@google.com>
Wed, 17 Jan 2018 01:34:52 +0000 (17:34 -0800)
committerSelim Cinek <cinek@google.com>
Thu, 18 Jan 2018 00:22:28 +0000 (16:22 -0800)
MessagingStyle wasn't properly picking up the remote input history,
but it was just ignored.
In addition was the display of 1to1 conversations wrong in that case.

Bug: 63708826
Test: manual add notification with MessagingStyle, reply.
Change-Id: I32141ecfb7dce948930de2477157f0fcddf7ba52

core/java/com/android/internal/widget/MessagingGroup.java
core/java/com/android/internal/widget/MessagingLayout.java
core/res/res/drawable/messaging_user.xml [new file with mode: 0644]
core/res/res/values/symbols.xml
packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java

index 20f05e6..33977f3 100644 (file)
@@ -60,6 +60,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
     private boolean mFirstLayout;
     private boolean mIsHidingAnimated;
     private boolean mNeedsGeneratedAvatar;
+    private Notification.Person mSender;
 
     public MessagingGroup(@NonNull Context context) {
         super(context);
@@ -89,6 +90,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
     }
 
     public void setSender(Notification.Person sender) {
+        mSender = sender;
         mSenderName.setText(sender.getName());
         mNeedsGeneratedAvatar = sender.getIcon() == null;
         if (!mNeedsGeneratedAvatar) {
@@ -355,7 +357,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
         return 0;
     }
 
-    public View getSender() {
+    public View getSenderView() {
         return mSenderName;
     }
 
@@ -370,4 +372,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou
     public boolean needsGeneratedAvatar() {
         return mNeedsGeneratedAvatar;
     }
+
+    public Notification.Person getSender() {
+        return mSender;
+    }
 }
index 834c93a..7a64cad 100644 (file)
@@ -35,7 +35,6 @@ import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.view.RemotableViewMethod;
-import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
@@ -135,9 +134,24 @@ public class MessagingLayout extends FrameLayout {
         if (headerText != null) {
             mConversationTitle = headerText.getText();
         }
+        addRemoteInputHistoryToMessages(newMessages,
+                extras.getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY));
         bind(newMessages, newHistoricMessages);
     }
 
+    private void addRemoteInputHistoryToMessages(
+            List<Notification.MessagingStyle.Message> newMessages,
+            CharSequence[] remoteInputHistory) {
+        if (remoteInputHistory == null || remoteInputHistory.length == 0) {
+            return;
+        }
+        for (int i = remoteInputHistory.length - 1; i >= 0; i--) {
+            CharSequence message = remoteInputHistory[i];
+            newMessages.add(new Notification.MessagingStyle.Message(
+                    message, 0, (Notification.Person) null));
+        }
+    }
+
     private void bind(List<Notification.MessagingStyle.Message> newMessages,
             List<Notification.MessagingStyle.Message> newHistoricMessages) {
 
@@ -189,9 +203,10 @@ public class MessagingLayout extends FrameLayout {
         for (int i = 0; i < mGroups.size(); i++) {
             // Let's now set the avatars
             MessagingGroup group = mGroups.get(i);
+            boolean isOwnMessage = group.getSender() == mUser;
             CharSequence senderName = group.getSenderName();
             if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)
-                    || (mIsOneToOne && mLargeIcon != null)) {
+                    || (mIsOneToOne && mLargeIcon != null && !isOwnMessage)) {
                 continue;
             }
             String symbol = uniqueNames.get(senderName);
@@ -209,7 +224,7 @@ public class MessagingLayout extends FrameLayout {
             if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)) {
                 continue;
             }
-            if (mIsOneToOne && mLargeIcon != null) {
+            if (mIsOneToOne && mLargeIcon != null && group.getSender() != mUser) {
                 group.setAvatar(mLargeIcon);
             } else {
                 Icon cachedIcon = cachedAvatars.get(senderName);
@@ -271,6 +286,12 @@ public class MessagingLayout extends FrameLayout {
 
     public void setUser(Notification.Person user) {
         mUser = user;
+        if (mUser.getIcon() == null) {
+            Icon userIcon = Icon.createWithResource(getContext(),
+                    com.android.internal.R.drawable.messaging_user);
+            userIcon.setTint(mLayoutColor);
+            mUser.setIcon(userIcon);
+        }
     }
 
     private void addMessagesToGroups(List<MessagingMessage> historicMessages,
@@ -410,7 +431,7 @@ public class MessagingLayout extends FrameLayout {
                             continue;
                         }
                         MessagingPropertyAnimator.fadeIn(group.getAvatar());
-                        MessagingPropertyAnimator.fadeIn(group.getSender());
+                        MessagingPropertyAnimator.fadeIn(group.getSenderView());
                         MessagingPropertyAnimator.startLocalTranslationFrom(group,
                                 group.getHeight(), LINEAR_OUT_SLOW_IN);
                     }
diff --git a/core/res/res/drawable/messaging_user.xml b/core/res/res/drawable/messaging_user.xml
new file mode 100644 (file)
index 0000000..3137698
--- /dev/null
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportHeight="192.0"
+        android:viewportWidth="192.0">
+    <path android:fillColor="#000000"
+          android:fillAlpha="0.125"
+          android:pathData="M96,0C43.01,0 0,43.01 0,96s43.01,96 96,96s96,-43.01 96,-96S148.99,0 96,0z"/>
+    <path android:fillColor="#BDBDBD"
+          android:pathData="M96,85.09c13.28,0 24,-10.72 24,-24c0,-13.28 -10.72,-24 -24,-24s-24,10.72 -24,24C72,74.37 82.72,85.09 96,85.09z"/>
+    <path android:fillColor="#BDBDBD"
+          android:pathData="M96,99.27c-29.33,0 -52.36,14.18 -52.36,27.27c11.09,17.06 30.51,28.36 52.36,28.36s41.27,-11.3 52.36,-28.36C148.36,113.45 125.33,99.27 96,99.27z"/>
+</vector>
index 638f1b2..6e33648 100644 (file)
 
   <java-symbol type="string" name="global_action_logout" />
   <java-symbol type="string" name="config_mainBuiltInDisplayCutout" />
+  <java-symbol type="drawable" name="messaging_user" />
   <java-symbol type="bool" name="config_fillMainBuiltInDisplayCutout" />
   <java-symbol type="drawable" name="ic_logout" />
 
index 7e0dba5..9c893b6 100644 (file)
@@ -67,6 +67,7 @@ public class NotificationData {
 
     public static final class Entry {
         private static final long LAUNCH_COOLDOWN = 2000;
+        private static final long REMOTE_INPUT_COOLDOWN = 500;
         private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
         private static final int COLOR_INVALID = 1;
         public String key;
@@ -92,6 +93,8 @@ public class NotificationData {
         private int mCachedContrastColorIsFor = COLOR_INVALID;
         private InflationTask mRunningTask = null;
         private Throwable mDebugThrowable;
+        public CharSequence remoteInputTextWhenReset;
+        public long lastRemoteInputSent = NOT_LAUNCHED_YET;
 
         public Entry(StatusBarNotification n) {
             this.key = n.getKey();
@@ -132,6 +135,10 @@ public class NotificationData {
             return SystemClock.elapsedRealtime() < lastFullScreenIntentLaunchTime + LAUNCH_COOLDOWN;
         }
 
+        public boolean hasJustSentRemoteInput() {
+            return SystemClock.elapsedRealtime() < lastRemoteInputSent + REMOTE_INPUT_COOLDOWN;
+        }
+
         /**
          * Create the icons for a notification
          * @param context the context to create the icons with
index 6bbd09f..6249ace 100644 (file)
@@ -35,6 +35,7 @@ import android.provider.Settings;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationStats;
 import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.EventLog;
 import android.util.Log;
@@ -462,7 +463,8 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
         mMediaManager.onNotificationRemoved(key);
 
         NotificationData.Entry entry = mNotificationData.get(key);
-        if (FORCE_REMOTE_INPUT_HISTORY && mRemoteInputManager.getController().isSpinning(key)
+        if (FORCE_REMOTE_INPUT_HISTORY
+                && shouldKeepForRemoteInput(entry)
                 && entry.row != null && !entry.row.isDismissed()) {
             StatusBarNotification sbn = entry.notification;
 
@@ -477,7 +479,11 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
                 newHistory = new CharSequence[oldHistory.length + 1];
                 System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length);
             }
-            newHistory[0] = String.valueOf(entry.remoteInputText);
+            CharSequence remoteInputText = entry.remoteInputText;
+            if (TextUtils.isEmpty(remoteInputText)) {
+                remoteInputText = entry.remoteInputTextWhenReset;
+            }
+            newHistory[0] = String.valueOf(remoteInputText);
             b.setRemoteInputHistory(newHistory);
 
             Notification newNotification = b.build();
@@ -539,6 +545,19 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
         mCallback.onNotificationRemoved(key, old);
     }
 
+    private boolean shouldKeepForRemoteInput(NotificationData.Entry entry) {
+        if (entry == null) {
+            return false;
+        }
+        if (mRemoteInputManager.getController().isSpinning(entry.key)) {
+            return true;
+        }
+        if (entry.hasJustSentRemoteInput()) {
+            return true;
+        }
+        return false;
+    }
+
     private StatusBarNotification removeNotificationViews(String key,
             NotificationListenerService.RankingMap ranking) {
         NotificationData.Entry entry = mNotificationData.remove(key, ranking);
index 27defca..113118a 100644 (file)
@@ -26,9 +26,7 @@ import com.android.internal.widget.MessagingLayout;
 import com.android.internal.widget.MessagingLinearLayout;
 import com.android.internal.widget.MessagingMessage;
 import com.android.internal.widget.MessagingPropertyAnimator;
-import com.android.internal.widget.ViewClippingUtil;
 import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -157,8 +155,8 @@ public class MessagingLayoutTransformState extends TransformState {
             setClippingDeactivated(child, true);
         }
         appear(ownGroup.getAvatar(), transformationAmount);
-        appear(ownGroup.getSender(), transformationAmount);
-        setClippingDeactivated(ownGroup.getSender(), true);
+        appear(ownGroup.getSenderView(), transformationAmount);
+        setClippingDeactivated(ownGroup.getSenderView(), true);
         setClippingDeactivated(ownGroup.getAvatar(), true);
     }
 
@@ -170,7 +168,7 @@ public class MessagingLayoutTransformState extends TransformState {
         } else {
             relativeOffset = (1.0f - transformationAmount) * mRelativeTranslationOffset;
         }
-        if (ownGroup.getSender().getVisibility() != View.GONE) {
+        if (ownGroup.getSenderView().getVisibility() != View.GONE) {
             relativeOffset *= 0.5f;
         }
         ownGroup.getMessageContainer().setTranslationY(relativeOffset);
@@ -188,8 +186,8 @@ public class MessagingLayoutTransformState extends TransformState {
             setClippingDeactivated(child, true);
         }
         disappear(ownGroup.getAvatar(), transformationAmount);
-        disappear(ownGroup.getSender(), transformationAmount);
-        setClippingDeactivated(ownGroup.getSender(), true);
+        disappear(ownGroup.getSenderView(), transformationAmount);
+        setClippingDeactivated(ownGroup.getSenderView(), true);
         setClippingDeactivated(ownGroup.getAvatar(), true);
     }
 
@@ -226,7 +224,7 @@ public class MessagingLayoutTransformState extends TransformState {
 
     private void transformGroups(MessagingGroup ownGroup, MessagingGroup otherGroup,
             float transformationAmount, boolean to) {
-        transformView(transformationAmount, to, ownGroup.getSender(), otherGroup.getSender(),
+        transformView(transformationAmount, to, ownGroup.getSenderView(), otherGroup.getSenderView(),
                 true /* sameAsAny */);
         transformView(transformationAmount, to, ownGroup.getAvatar(), otherGroup.getAvatar(),
                 true /* sameAsAny */);
@@ -345,7 +343,7 @@ public class MessagingLayoutTransformState extends TransformState {
                     setVisible(child, visible, force);
                 }
                 setVisible(ownGroup.getAvatar(), visible, force);
-                setVisible(ownGroup.getSender(), visible, force);
+                setVisible(ownGroup.getSenderView(), visible, force);
             }
         }
     }
@@ -376,9 +374,9 @@ public class MessagingLayoutTransformState extends TransformState {
                     setClippingDeactivated(child, false);
                 }
                 resetTransformedView(ownGroup.getAvatar());
-                resetTransformedView(ownGroup.getSender());
+                resetTransformedView(ownGroup.getSenderView());
                 setClippingDeactivated(ownGroup.getAvatar(), false);
-                setClippingDeactivated(ownGroup.getSender(), false);
+                setClippingDeactivated(ownGroup.getSenderView(), false);
                 ownGroup.setTranslationY(0);
                 ownGroup.getMessageContainer().setTranslationY(0);
             }
index 4fc5044..c377feb 100644 (file)
@@ -27,7 +27,9 @@ import android.content.pm.ShortcutManager;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.SystemClock;
 import android.text.Editable;
+import android.text.SpannedString;
 import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -140,6 +142,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
         mSendButton.setVisibility(INVISIBLE);
         mProgressBar.setVisibility(VISIBLE);
         mEntry.remoteInputText = mEditText.getText();
+        mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime();
         mController.addSpinning(mEntry.key, mToken);
         mController.removeRemoteInput(mEntry, mToken);
         mEditText.mShowImeOnInputConnection = false;
@@ -298,6 +301,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
 
     private void reset() {
         mResetting = true;
+        mEntry.remoteInputTextWhenReset = SpannedString.valueOf(mEditText.getText());
 
         mEditText.getText().clear();
         mEditText.setEnabled(true);