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

Commit cc0fbf9c authored by Lucas Dupin's avatar Lucas Dupin
Browse files

use new theme colors on custom notifications

Custom notifications are inflated using a different context, text colors
should be replaced after infaltion, similarly to what we do on dark
mode.

Test: manual
Test: atest com.android.systemui.statusbar.notification.row
Fixes: 174763901
Change-Id: I009011a66056cb31c026b48217710c5f3d74b0b5
parent 73665572
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -489,7 +489,6 @@

    <style name="TextAppearance.NotificationInfo">
        <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
        <item name="android:textColor">@color/notification_primary_text_color</item>
    </style>

    <style name="TextAppearance.NotificationInfo.Secondary">
@@ -498,7 +497,6 @@
    </style>

    <style name="TextAppearance.NotificationInfo.Title">
        <item name="android:textColor">@color/notification_primary_text_color</item>
        <item name="android:textStyle">bold</item>
    </style>

+4 −0
Original line number Diff line number Diff line
@@ -47,6 +47,10 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
    public void onContentUpdated(ExpandableNotificationRow row) {
        super.onContentUpdated(row);

        // Custom views will most likely use just white or black as their text color.
        // We need to scan through and replace these colors by Material NEXT colors.
        ensureThemeOnChildren();

        // Let's invert the notification colors when we're in night mode and
        // the notification background isn't colorized.
        if (needsInversion(mBackgroundColor, mView)) {
+5 −0
Original line number Diff line number Diff line
@@ -43,6 +43,11 @@ public class NotificationDecoratedCustomViewWrapper extends NotificationTemplate
        if (childIndex != null && childIndex != -1) {
            mWrappedView = container.getChildAt(childIndex);
        }

        // Custom views will most likely use just white or black as their text color.
        // We need to scan through and replace these colors by Material NEXT colors.
        ensureThemeOnChildren();

        if (needsInversion(resolveBackgroundColor(), mWrappedView)) {
            invertViewLuminosity(mWrappedView);
        }
+50 −0
Original line number Diff line number Diff line
@@ -29,11 +29,13 @@ import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.ContextThemeWrapper;
import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ContrastColorUtil;
@@ -55,6 +57,9 @@ public abstract class NotificationViewWrapper implements TransformableView {
    private final Rect mTmpRect = new Rect();

    protected int mBackgroundColor = 0;
    private int mLightTextColor;
    private int mDarkTextColor;
    private int mDefaultTextColor;

    public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
        if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -110,6 +115,15 @@ public abstract class NotificationViewWrapper implements TransformableView {
            mBackgroundColor = backgroundColor;
            mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
        }
        mLightTextColor = mView.getContext().getColor(
                com.android.internal.R.color.notification_primary_text_color_light);
        mDarkTextColor = mView.getContext().getColor(
                R.color.notification_primary_text_color_dark);

        Context themedContext = new ContextThemeWrapper(mView.getContext(),
                R.style.Theme_DeviceDefault_DayNight);
        mDefaultTextColor = Utils.getColorAttr(themedContext, R.attr.textColorPrimary)
                .getDefaultColor();
    }

    protected boolean needsInversion(int defaultBackgroundColor, View view) {
@@ -187,6 +201,42 @@ public abstract class NotificationViewWrapper implements TransformableView {
        return false;
    }

    protected void ensureThemeOnChildren() {
        if (mView == null) {
            return;
        }

        // Notifications with custom backgrounds should not be adjusted
        if (mBackgroundColor != Color.TRANSPARENT
                || getBackgroundColor(mView) != Color.TRANSPARENT) {
            return;
        }

        // Now let's check if there's unprotected text somewhere, and apply the theme if we find it.
        if (!(mView instanceof ViewGroup)) {
            return;
        }
        processChildrenTextColor((ViewGroup) mView);
    }

    private void processChildrenTextColor(ViewGroup viewGroup) {
        if (viewGroup == null) {
            return;
        }

        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View child = viewGroup.getChildAt(i);
            if (child instanceof TextView) {
                int foreground = ((TextView) child).getCurrentTextColor();
                if (foreground == mLightTextColor || foreground == mDarkTextColor) {
                    ((TextView) child).setTextColor(mDefaultTextColor);
                }
            } else if (child instanceof ViewGroup) {
                processChildrenTextColor((ViewGroup) child);
            }
        }
    }

    protected int getBackgroundColor(View view) {
        if (view == null) {
            return Color.TRANSPARENT;
+6 −0
Original line number Diff line number Diff line
@@ -81,12 +81,15 @@ public class NotificationContentViewTest extends SysuiTestCase {
        View mockContracted = mock(NotificationHeaderView.class);
        when(mockContracted.findViewById(com.android.internal.R.id.feedback))
                .thenReturn(mockContracted);
        when(mockContracted.getContext()).thenReturn(mContext);
        View mockExpanded = mock(NotificationHeaderView.class);
        when(mockExpanded.findViewById(com.android.internal.R.id.feedback))
                .thenReturn(mockExpanded);
        when(mockExpanded.getContext()).thenReturn(mContext);
        View mockHeadsUp = mock(NotificationHeaderView.class);
        when(mockHeadsUp.findViewById(com.android.internal.R.id.feedback))
                .thenReturn(mockHeadsUp);
        when(mockHeadsUp.getContext()).thenReturn(mContext);

        mView.setContractedChild(mockContracted);
        mView.setExpandedChild(mockExpanded);
@@ -107,18 +110,21 @@ public class NotificationContentViewTest extends SysuiTestCase {
        when(mockContracted.animate()).thenReturn(mock(ViewPropertyAnimator.class));
        when(mockContracted.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
                mockContractedEB);
        when(mockContracted.getContext()).thenReturn(mContext);

        View mockExpandedEB = mock(NotificationExpandButton.class);
        View mockExpanded = mock(NotificationHeaderView.class);
        when(mockExpanded.animate()).thenReturn(mock(ViewPropertyAnimator.class));
        when(mockExpanded.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
                mockExpandedEB);
        when(mockExpanded.getContext()).thenReturn(mContext);

        View mockHeadsUpEB = mock(NotificationExpandButton.class);
        View mockHeadsUp = mock(NotificationHeaderView.class);
        when(mockHeadsUp.animate()).thenReturn(mock(ViewPropertyAnimator.class));
        when(mockHeadsUp.findViewById(com.android.internal.R.id.expand_button)).thenReturn(
                mockHeadsUpEB);
        when(mockHeadsUp.getContext()).thenReturn(mContext);

        // Set up all 3 child forms
        mView.setContractedChild(mockContracted);
Loading