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

Commit e65344f0 authored by Ibrahim Yilmaz's avatar Ibrahim Yilmaz Committed by Android (Google) Code Review
Browse files

Merge "[Minimal HUN] Messaging Minimal HUN" into main

parents 8abd377b 3cbc2ecb
Loading
Loading
Loading
Loading
+75 −2
Original line number Diff line number Diff line
@@ -5704,6 +5704,7 @@ public class Notification implements Parcelable
            p.headerless(resId == getBaseLayoutResource()
                    || resId == getHeadsUpBaseLayoutResource()
                    || resId == getCompactHeadsUpBaseLayoutResource()
                    || resId == getMessagingCompactHeadsUpLayoutResource()
                    || resId == getMessagingLayoutResource()
                    || resId == R.layout.notification_template_material_media);
            RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
@@ -7294,6 +7295,10 @@ public class Notification implements Parcelable
            return R.layout.notification_template_material_compact_heads_up_base;
        }
        private int getMessagingCompactHeadsUpLayoutResource() {
            return R.layout.notification_template_material_messaging_compact_heads_up;
        }
        private int getBigBaseLayoutResource() {
            return R.layout.notification_template_material_big_base;
        }
@@ -9166,10 +9171,78 @@ public class Notification implements Parcelable
        @Nullable
        @Override
        public RemoteViews makeCompactHeadsUpContentView() {
            // TODO(b/336229954): Apply minimal HUN treatment to Messaging Notifications.
            return makeHeadsUpContentView(false);
            final boolean isConversationLayout = mConversationType != CONVERSATION_TYPE_LEGACY;
            Icon conversationIcon = null;
            Notification.Action remoteInputAction = null;
            if (isConversationLayout) {
                conversationIcon = mShortcutIcon;
                // conversation icon is m
                // Extract the conversation icon for one to one conversations from
                // the latest incoming message since
                // fixTitleAndTextExtras also uses it as data source for title and text
                if (conversationIcon == null && !mIsGroupConversation) {
                    final Message message = findLatestIncomingMessage();
                    if (message != null) {
                        final Person sender = message.mSender;
                        if (sender != null) {
                            conversationIcon = sender.getIcon();
                        }
                    }
                }
                if (Flags.compactHeadsUpNotificationReply()) {
                    // Get the first non-contextual inline reply action.
                    final List<Notification.Action> nonContextualActions =
                            mBuilder.getNonContextualActions();
                    for (int i = 0; i < nonContextualActions.size(); i++) {
                        final Notification.Action action = nonContextualActions.get(i);
                        if (mBuilder.hasValidRemoteInput(action)) {
                            remoteInputAction = action;
                            break;
                        }
                    }
                }
            }
            // This method fills title and text
            fixTitleAndTextExtras(mBuilder.mN.extras);
            final StandardTemplateParams p = mBuilder.mParams.reset()
                    .viewType(StandardTemplateParams.VIEW_TYPE_HEADS_UP)
                    .highlightExpander(isConversationLayout)
                    .fillTextsFrom(mBuilder)
                    .hideTime(true)
                    .summaryText("");
            p.headerTextSecondary(p.mText);
            TemplateBindResult bindResult = new TemplateBindResult();
            RemoteViews contentView = mBuilder.applyStandardTemplate(
                    mBuilder.getMessagingCompactHeadsUpLayoutResource(), p, bindResult);
            if (conversationIcon != null) {
                contentView.setViewVisibility(R.id.icon, View.GONE);
                contentView.setViewVisibility(R.id.conversation_icon, View.VISIBLE);
                contentView.setBoolean(R.id.conversation_icon, "setApplyCircularCrop", true);
                contentView.setImageViewIcon(R.id.conversation_icon, conversationIcon);
            }
            if (remoteInputAction != null) {
                contentView.setViewVisibility(R.id.reply_action_container, View.VISIBLE);
                final RemoteViews inlineReplyButton =
                        mBuilder.generateActionButton(remoteInputAction, false, p);
                // Clear the drawable
                inlineReplyButton.setInt(R.id.action0, "setBackgroundResource", 0);
                inlineReplyButton.setTextViewText(R.id.action0,
                        mBuilder.mContext.getString(R.string.notification_compact_heads_up_reply));
                contentView.addView(R.id.reply_action_container, inlineReplyButton);
            } else {
                contentView.setViewVisibility(R.id.reply_action_container, View.GONE);
            }
            return contentView;
        }
        /**
         * @hide
         */
+7 −0
Original line number Diff line number Diff line
@@ -160,3 +160,10 @@ flag {
  description: "[Minimal HUN] Enables the compact heads up notification feature"
  bug: "270709257"
}

flag {
  name: "compact_heads_up_notification_reply"
  namespace: "systemui"
  description: "[Minimal HUN] Enables the compact heads up notification reply capability for Conversation Notifications"
  bug: "336229954"
}
 No newline at end of file
+89 −2
Original line number Diff line number Diff line
@@ -16,18 +16,27 @@

package com.android.internal.widget;

import android.annotation.Nullable;
import android.app.Flags;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.util.AttributeSet;
import android.view.RemotableViewMethod;
import android.widget.RemoteViews;

import androidx.annotation.Nullable;

/**
 * An image view that holds the icon displayed on the left side of a notification row.
 */
@RemoteViews.RemoteView
public class NotificationRowIconView extends CachingIconView {
    private boolean mApplyCircularCrop = false;

    public NotificationRowIconView(Context context) {
        super(context);
    }
@@ -57,4 +66,82 @@ public class NotificationRowIconView extends CachingIconView {

        super.onFinishInflate();
    }

    @Nullable
    @Override
    Drawable loadSizeRestrictedIcon(@Nullable Icon icon) {
        final Drawable original = super.loadSizeRestrictedIcon(icon);
        final Drawable result;
        if (mApplyCircularCrop) {
            result = makeCircularDrawable(original);
        } else {
            result = original;
        }

        return result;
    }

    /**
     * Enables circle crop that makes given image circular
     */
    @RemotableViewMethod(asyncImpl = "setApplyCircularCropAsync")
    public void setApplyCircularCrop(boolean applyCircularCrop) {
        mApplyCircularCrop = applyCircularCrop;
    }

    /**
     * Async version of {@link NotificationRowIconView#setApplyCircularCrop}
     */
    public Runnable setApplyCircularCropAsync(boolean applyCircularCrop) {
        mApplyCircularCrop = applyCircularCrop;
        return () -> {
        };
    }

    @Nullable
    private Drawable makeCircularDrawable(@Nullable Drawable original) {
        if (original == null) {
            return original;
        }

        final Bitmap source = drawableToBitmap(original);

        int size = Math.min(source.getWidth(), source.getHeight());

        Bitmap squared = Bitmap.createScaledBitmap(source, size, size, /* filter= */ false);
        Bitmap result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);

        final Canvas canvas = new Canvas(result);
        final Paint paint = new Paint();
        paint.setShader(
                new BitmapShader(squared, BitmapShader.TileMode.CLAMP,
                        BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float radius = size / 2f;
        canvas.drawCircle(radius, radius, radius, paint);
        return new BitmapDrawable(getResources(), result);
    }

    private static Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable bitmapDrawable) {
            final Bitmap bitmap = bitmapDrawable.getBitmap();
            if (bitmap.getConfig() == Bitmap.Config.HARDWARE) {
                return bitmap.copy(Bitmap.Config.ARGB_8888, false);
            } else {
                return bitmap;
            }
        }

        int width = drawable.getIntrinsicWidth();
        width = width > 0 ? width : 1;
        int height = drawable.getIntrinsicHeight();
        height = height > 0 ? height : 1;

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }
}
+104 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?><!--
  ~ Copyright (C) 2024 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
  -->
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/status_bar_latest_event_content"
    android:layout_width="match_parent"
    android:layout_height="@dimen/notification_header_height"
    android:clipChildren="false"
    android:tag="compactMessagingHUN"
    android:gravity="center_vertical"
    android:theme="@style/Theme.DeviceDefault.Notification"
    android:importantForAccessibility="no">
    <com.android.internal.widget.NotificationRowIconView
        android:id="@+id/icon"
        android:layout_width="@dimen/notification_icon_circle_size"
        android:layout_height="@dimen/notification_icon_circle_size"
        android:layout_gravity="center_vertical|start"
        android:layout_marginStart="@dimen/notification_icon_circle_start"
        android:background="@drawable/notification_icon_circle"
        android:padding="@dimen/notification_icon_circle_padding"
        android:maxDrawableWidth="@dimen/notification_icon_circle_size"
        android:maxDrawableHeight="@dimen/notification_icon_circle_size"
        />
    <com.android.internal.widget.NotificationRowIconView
        android:id="@+id/conversation_icon"
        android:layout_width="@dimen/notification_icon_circle_size"
        android:layout_height="@dimen/notification_icon_circle_size"
        android:layout_gravity="center_vertical|start"
        android:layout_marginStart="@dimen/notification_icon_circle_start"
        android:maxDrawableWidth="@dimen/notification_icon_circle_size"
        android:maxDrawableHeight="@dimen/notification_icon_circle_size"
        android:scaleType="centerCrop"
        android:importantForAccessibility="no"
        />
    <FrameLayout
        android:id="@+id/alternate_expand_target"
        android:layout_width="@dimen/notification_content_margin_start"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:importantForAccessibility="no"
        android:focusable="false"
        />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="@dimen/notification_content_margin_start"
        android:orientation="horizontal"
        >
        <NotificationTopLineView
            android:id="@+id/notification_top_line"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_centerVertical="true"
            android:layout_weight="1"
            android:clipChildren="false"
            android:gravity="center_vertical"
            android:theme="@style/Theme.DeviceDefault.Notification"
            >
            <TextView
                android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="@dimen/notification_header_separating_margin"
                android:ellipsize="end"
                android:fadingEdge="horizontal"
                android:singleLine="true"
                android:textAlignment="viewStart"
                android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
                />
            <include layout="@layout/notification_top_line_views" />
        </NotificationTopLineView>
        <FrameLayout
            android:id="@+id/reply_action_container"
            android:layout_width="wrap_content"
            android:layout_height="@dimen/notification_action_list_height"
            android:gravity="center_vertical"
            android:orientation="horizontal" />
        <FrameLayout
            android:id="@+id/expand_button_touch_container"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:minWidth="@dimen/notification_content_margin_end"
            >
            <include layout="@layout/notification_expand_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical|end"
                />
        </FrameLayout>
    </LinearLayout>
</FrameLayout>
+3 −0
Original line number Diff line number Diff line
@@ -794,6 +794,9 @@
    <!-- The divider symbol between different parts of the notification header including spaces. not translatable [CHAR LIMIT=3] -->
    <string name="notification_header_divider_symbol_with_spaces" translatable="false">" • "</string>

    <!-- Text for inline reply button for compact conversation heads ups -->
    <string name="notification_compact_heads_up_reply">Reply</string>

    <!-- Text shown in place of notification contents when the notification is hidden on a secure lockscreen -->
    <string name="notification_hidden_text">New notification</string>

Loading