private boolean mFirstLayout;
private boolean mIsHidingAnimated;
private boolean mNeedsGeneratedAvatar;
+ private Notification.Person mSender;
public MessagingGroup(@NonNull Context context) {
super(context);
}
public void setSender(Notification.Person sender) {
+ mSender = sender;
mSenderName.setText(sender.getName());
mNeedsGeneratedAvatar = sender.getIcon() == null;
if (!mNeedsGeneratedAvatar) {
return 0;
}
- public View getSender() {
+ public View getSenderView() {
return mSenderName;
}
public boolean needsGeneratedAvatar() {
return mNeedsGeneratedAvatar;
}
+
+ public Notification.Person getSender() {
+ return mSender;
+ }
}
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;
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) {
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);
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);
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,
continue;
}
MessagingPropertyAnimator.fadeIn(group.getAvatar());
- MessagingPropertyAnimator.fadeIn(group.getSender());
+ MessagingPropertyAnimator.fadeIn(group.getSenderView());
MessagingPropertyAnimator.startLocalTranslationFrom(group,
group.getHeight(), LINEAR_OUT_SLOW_IN);
}
--- /dev/null
+<!--
+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>
<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" />
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;
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();
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
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;
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;
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();
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);
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;
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);
}
} 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);
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);
}
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 */);
setVisible(child, visible, force);
}
setVisible(ownGroup.getAvatar(), visible, force);
- setVisible(ownGroup.getSender(), visible, force);
+ setVisible(ownGroup.getSenderView(), visible, force);
}
}
}
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);
}
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;
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;
private void reset() {
mResetting = true;
+ mEntry.remoteInputTextWhenReset = SpannedString.valueOf(mEditText.getText());
mEditText.getText().clear();
mEditText.setEnabled(true);