Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0dc61b5 authored by Selim Cinek's avatar Selim Cinek
Browse files

Hiding the icon of notifications that were replied to

Because those notifications now stay around but the user
has already seen them, were hiding the icon instead.

Change-Id: I6b8590e31295ed79218698b1ac54df33b273d38c
Fixes: 78486801
Test: add notification, reply, observe icon gone
parent 645c8671
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -7356,7 +7356,14 @@ public class Notification implements Parcelable
                return messages;
            }

            static Message getMessageFromBundle(Bundle bundle) {
            /**
             * @return The message that is stored in the bundle or null if the message couldn't be
             * resolved.
             *
             * @hide
             */
            @Nullable
            public static Message getMessageFromBundle(Bundle bundle) {
                try {
                    if (!bundle.containsKey(KEY_TEXT) || !bundle.containsKey(KEY_TIMESTAMP)) {
                        return null;
+43 −0
Original line number Diff line number Diff line
@@ -32,10 +32,13 @@ import android.app.AppGlobals;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Person;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.notification.NotificationListenerService.Ranking;
@@ -50,6 +53,7 @@ import android.widget.RemoteViews;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
@@ -117,6 +121,11 @@ public class NotificationData {
         */
        public Boolean mIsSystemNotification;

        /**
         * Has the user sent a reply through this Notification.
         */
        private boolean hasSentReply;

        public Entry(StatusBarNotification n) {
            this.key = n.getKey();
            this.notification = n;
@@ -298,6 +307,40 @@ public class NotificationData {
            lastRemoteInputSent = NOT_LAUNCHED_YET;
            remoteInputTextWhenReset = null;
        }

        public void setHasSentReply() {
            hasSentReply = true;
        }

        public boolean isLastMessageFromReply() {
            if (!hasSentReply) {
                return false;
            }
            Bundle extras = notification.getNotification().extras;
            CharSequence[] replyTexts = extras.getCharSequenceArray(
                    Notification.EXTRA_REMOTE_INPUT_HISTORY);
            if (!ArrayUtils.isEmpty(replyTexts)) {
                return true;
            }
            Parcelable[] messages = extras.getParcelableArray(Notification.EXTRA_MESSAGES);
            if (messages != null && messages.length > 0) {
                Parcelable message = messages[messages.length - 1];
                if (message instanceof Bundle) {
                    Notification.MessagingStyle.Message lastMessage =
                            Notification.MessagingStyle.Message.getMessageFromBundle(
                                    (Bundle) message);
                    if (lastMessage != null) {
                        Person senderPerson = lastMessage.getSenderPerson();
                        if (senderPerson == null) {
                            return true;
                        }
                        Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON);
                        return Objects.equals(user, senderPerson);
                    }
                }
            }
            return false;
        }
    }

    private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
+14 −6
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ public class NotificationIconAreaController implements DarkReceiver {
    }

    protected boolean shouldShowNotificationIcon(NotificationData.Entry entry,
            boolean showAmbient, boolean hideDismissed) {
            boolean showAmbient, boolean hideDismissed, boolean hideRepliedMessages) {
        if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
            return false;
        }
@@ -155,6 +155,10 @@ public class NotificationIconAreaController implements DarkReceiver {
            return false;
        }

        if (hideRepliedMessages && entry.isLastMessageFromReply()) {
            return false;
        }

        // showAmbient == show in shade but not shelf
        if (!showAmbient && mEntryManager.getNotificationData().shouldSuppressStatusBar(entry)) {
            return false;
@@ -170,14 +174,15 @@ public class NotificationIconAreaController implements DarkReceiver {

        updateStatusBarIcons();
        updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
                NotificationShelf.SHOW_AMBIENT_ICONS, false /* hideDismissed */);
                NotificationShelf.SHOW_AMBIENT_ICONS, false /* hideDismissed */,
                false /* hideRepliedMessages */);

        applyNotificationIconsTint();
    }

    private void updateStatusBarIcons() {
    public void updateStatusBarIcons() {
        updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
                false /* showAmbient */, true /* hideDismissed */);
                false /* showAmbient */, true /* hideDismissed */, true /* hideRepliedMessages */);
    }

    /**
@@ -187,9 +192,11 @@ public class NotificationIconAreaController implements DarkReceiver {
     * @param hostLayout which layout should be updated
     * @param showAmbient should ambient notification icons be shown
     * @param hideDismissed should dismissed icons be hidden
     * @param hideRepliedMessages should messages that have been replied to be hidden
     */
    private void updateIconsForLayout(Function<NotificationData.Entry, StatusBarIconView> function,
            NotificationIconContainer hostLayout, boolean showAmbient, boolean hideDismissed) {
            NotificationIconContainer hostLayout, boolean showAmbient, boolean hideDismissed,
            boolean hideRepliedMessages) {
        ArrayList<StatusBarIconView> toShow = new ArrayList<>(
                mNotificationScrollLayout.getChildCount());

@@ -198,7 +205,8 @@ public class NotificationIconAreaController implements DarkReceiver {
            View view = mNotificationScrollLayout.getChildAt(i);
            if (view instanceof ExpandableNotificationRow) {
                NotificationData.Entry ent = ((ExpandableNotificationRow) view).getEntry();
                if (shouldShowNotificationIcon(ent, showAmbient, hideDismissed)) {
                if (shouldShowNotificationIcon(ent, showAmbient, hideDismissed,
                        hideRepliedMessages)) {
                    toShow.add(function.apply(ent));
                }
            }
+1 −0
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        mController.removeRemoteInput(mEntry, mToken);
        mEditText.mShowImeOnInputConnection = false;
        mController.remoteInputSent(mEntry);
        mEntry.setHasSentReply();

        // Tell ShortcutManager that this package has been "activated".  ShortcutManager
        // will reset the throttling for this package.
+1 −0
Original line number Diff line number Diff line
@@ -212,6 +212,7 @@ public class SmartReplyView extends ViewGroup {
            Intent intent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            RemoteInput.addResultsToIntent(new RemoteInput[]{remoteInput}, intent, results);
            RemoteInput.setResultsSource(intent, RemoteInput.SOURCE_CHOICE);
            entry.setHasSentReply();
            try {
                pendingIntent.send(context, 0, intent);
            } catch (PendingIntent.CanceledException e) {