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

Commit e5e74e73 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Updates to notif channel blocking UI

- Ensure 'see more' and 'done' buttons are always visible in landscape
- Since the channel list is now scrollable for the above, include all
channels that have sent a notification in the last 2 weeks, and all the
blocked channels
- Group channels by channel group, order alphabetically in a group
- do some cleanup of 'channel set', which hasn't been used for a long
time (if you long press on a summary with children with multiple
channels we just expand the group)

Test: ChannelEditorDialogControllerTest
Test: NotificationInfoTest
Test: PartialConversationInfoTest
Test: PreferencesHelperTest
Test: NotificationGutsManagerTest
Test: Make display and text as big as possible, and view dialog in
portrait and landscape on apps that have 1, 3, many channels
Fixes: 292179820

Change-Id: If8734723d6cbc0b0ac6dd6fae0e4924b48b6768a
parent f8e724fa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ interface INotificationManager
    ParceledListSlice getNotificationChannelGroupsForPackage(String pkg, int uid, boolean includeDeleted);
    NotificationChannelGroup getNotificationChannelGroupForPackage(String groupId, String pkg, int uid);
    NotificationChannelGroup getPopulatedNotificationChannelGroupForPackage(String pkg, int uid, String groupId, boolean includeDeleted);
    ParceledListSlice getRecentBlockedNotificationChannelGroupsForPackage(String pkg, int uid);
    void updateNotificationChannelGroupForPackage(String pkg, int uid, in NotificationChannelGroup group);
    void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
    void unlockNotificationChannel(String pkg, int uid, String channelId);
+19 −12
Original line number Diff line number Diff line
@@ -22,8 +22,7 @@
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|bottom"
        android:paddingStart="4dp"
        android:paddingEnd="4dp"
>
        android:paddingEnd="4dp">

    <LinearLayout
        android:id="@+id/half_shelf"
@@ -82,11 +81,21 @@
                    android:theme="@style/MainSwitch.Settingslib"/>
            </com.android.systemui.statusbar.notification.row.AppControlView>

            <ScrollView
                android:layout_width="match_parent"
                android:layout_height="@dimen/notification_blocker_channel_list_height"
                android:clipToPadding="false">
                <LinearLayout
                    android:id="@+id/scrollView"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">
                    <!-- ChannelRows get added dynamically -->

                </LinearLayout>
            </ScrollView>
        </com.android.systemui.statusbar.notification.row.ChannelEditorListView>

        <RelativeLayout
        <LinearLayout
            android:id="@+id/bottom_actions"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
@@ -98,25 +107,23 @@
                android:text="@string/see_more_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentStart="true"
                android:layout_centerVertical="true"
                android:gravity="start|center_vertical"
                android:minWidth="@dimen/notification_importance_toggle_size"
                android:minHeight="@dimen/notification_importance_toggle_size"
                android:maxWidth="200dp"
                style="@style/Widget.Dialog.Button"/>
            <Space
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1" />
            <TextView
                android:id="@+id/done_button"
                android:text="@string/inline_ok_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:gravity="end|center_vertical"
                android:maxWidth="125dp"
                android:minWidth="@dimen/notification_importance_toggle_size"
                android:minHeight="@dimen/notification_importance_toggle_size"
                android:layout_alignParentEnd="true"
                style="@style/Widget.Dialog.Button"/>
        </RelativeLayout>
        </LinearLayout>
    </LinearLayout>
</FrameLayout>
+3 −0
Original line number Diff line number Diff line
@@ -89,6 +89,9 @@
    <dimen name="global_actions_button_size">72dp</dimen>
    <dimen name="global_actions_button_padding">26dp</dimen>

    <!-- scroll view the size of 2 channel rows -->
    <dimen name="notification_blocker_channel_list_height">128dp</dimen>

    <dimen name="keyguard_indication_margin_bottom">8dp</dimen>
    <dimen name="lock_icon_margin_bottom">24dp</dimen>
</resources>
+2 −0
Original line number Diff line number Diff line
@@ -313,6 +313,8 @@
    <!-- The space around a notification menu item  -->
    <dimen name="notification_menu_icon_padding">20dp</dimen>

    <!-- scroll view the size of 3 channel rows -->
    <dimen name="notification_blocker_channel_list_height">192dp</dimen>
    <!-- The vertical space around the buttons in the inline settings -->
    <dimen name="notification_guts_button_spacing">12dp</dimen>

+23 −38
Original line number Diff line number Diff line
@@ -71,15 +71,15 @@ class ChannelEditorDialogController @Inject constructor(
    private var appUid: Int? = null
    private var packageName: String? = null
    private var appName: String? = null
    private var channel: NotificationChannel? = null
    private var onSettingsClickListener: NotificationInfo.OnSettingsClickListener? = null

    // Caller should set this if they care about when we dismiss
    var onFinishListener: OnChannelEditorDialogFinishedListener? = null

    @VisibleForTesting
    internal val paddedChannels = mutableListOf<NotificationChannel>()
    // Channels handed to us from NotificationInfo
    private val providedChannels = mutableListOf<NotificationChannel>()
    @VisibleForTesting
    internal val channelList = mutableListOf<NotificationChannel>()

    // Map from NotificationChannel to importance
    private val edits = mutableMapOf<NotificationChannel, Int>()
@@ -93,14 +93,14 @@ class ChannelEditorDialogController @Inject constructor(
    private val channelGroupList = mutableListOf<NotificationChannelGroup>()

    /**
     * Give the controller all of the information it needs to present the dialog
     * Give the controller all the information it needs to present the dialog
     * for a given app. Does a bunch of querying of NoMan, but won't present anything yet
     */
    fun prepareDialogForApp(
        appName: String,
        packageName: String,
        uid: Int,
        channels: Set<NotificationChannel>,
        channel: NotificationChannel,
        appIcon: Drawable,
        onSettingsClickListener: NotificationInfo.OnSettingsClickListener?
    ) {
@@ -110,6 +110,7 @@ class ChannelEditorDialogController @Inject constructor(
        this.appIcon = appIcon
        this.appNotificationsEnabled = checkAreAppNotificationsOn()
        this.onSettingsClickListener = onSettingsClickListener
        this.channel = channel

        // These will always start out the same
        appNotificationsCurrentlyEnabled = appNotificationsEnabled
@@ -117,9 +118,7 @@ class ChannelEditorDialogController @Inject constructor(
        channelGroupList.clear()
        channelGroupList.addAll(fetchNotificationChannelGroups())
        buildGroupNameLookup()
        providedChannels.clear()
        providedChannels.addAll(channels)
        padToFourChannels(channels)
        populateChannelList()
        initDialog()

        prepared = true
@@ -133,34 +132,24 @@ class ChannelEditorDialogController @Inject constructor(
        }
    }

    private fun padToFourChannels(channels: Set<NotificationChannel>) {
        paddedChannels.clear()
        // First, add all of the given channels
        paddedChannels.addAll(channels.asSequence().take(4))

        // Then pad to 4 if we haven't been given that many
        paddedChannels.addAll(getDisplayableChannels(channelGroupList.asSequence())
                .filterNot { paddedChannels.contains(it) }
                .distinct()
                .take(4 - paddedChannels.size))

        // If we only got one channel and it has the default miscellaneous tag, then we actually
        // are looking at an app with a targetSdk <= O, and it doesn't make much sense to show the
        // channel
        if (paddedChannels.size == 1 && DEFAULT_CHANNEL_ID == paddedChannels[0].id) {
            paddedChannels.clear()
    private fun populateChannelList() {
        channelList.clear()
        if (DEFAULT_CHANNEL_ID != channel!!.id) {
            channelList.add(0, channel!!)
            channelList.addAll(getDisplayableChannels(channelGroupList.asSequence())
                    .filterNot { it.id == channel!!.id }
                    .distinct())
        }
    }

    private fun getDisplayableChannels(
        groupList: Sequence<NotificationChannelGroup>
    ): Sequence<NotificationChannel> {

        // TODO (b/194833441): remove channel level settings when we move to a permission
        val channels = groupList
                .flatMap { group ->
                    group.channels.asSequence().filterNot { channel ->
                        channel.importance == IMPORTANCE_NONE ||
                    group.channels.asSequence()
                            .sortedWith(compareBy {group.name?.toString() ?: group.id})
                            .filterNot { channel ->
                                channel.isImportanceLockedByCriticalDeviceFunction
                            }
                }
@@ -196,8 +185,7 @@ class ChannelEditorDialogController @Inject constructor(
        appNotificationsCurrentlyEnabled = null

        edits.clear()
        paddedChannels.clear()
        providedChannels.clear()
        channelList.clear()
        groupNameLookup.clear()
    }

@@ -231,7 +219,7 @@ class ChannelEditorDialogController @Inject constructor(
    @Suppress("unchecked_cast")
    private fun fetchNotificationChannelGroups(): List<NotificationChannelGroup> {
        return try {
            noMan.getNotificationChannelGroupsForPackage(packageName!!, appUid!!, false)
            noMan.getRecentBlockedNotificationChannelGroupsForPackage(packageName!!, appUid!!)
                    .list as? List<NotificationChannelGroup> ?: listOf()
        } catch (e: Exception) {
            Log.e(TAG, "Error fetching channel groups", e)
@@ -280,7 +268,6 @@ class ChannelEditorDialogController @Inject constructor(

    @VisibleForTesting
    fun launchSettings(sender: View) {
        val channel = if (providedChannels.size == 1) providedChannels[0] else null
        onSettingsClickListener?.onClick(sender, channel, appUid!!)
    }

@@ -301,14 +288,12 @@ class ChannelEditorDialogController @Inject constructor(
                controller = this@ChannelEditorDialogController
                appIcon = this@ChannelEditorDialogController.appIcon
                appName = this@ChannelEditorDialogController.appName
                channels = paddedChannels
                channels = channelList
            }

            setOnShowListener {
                // play a highlight animation for the given channels
                for (channel in providedChannels) {
                    listView?.highlightChannel(channel)
                }
                // play a highlight animation for the given channel
                listView?.highlightChannel(channel!!)
            }

            findViewById<TextView>(R.id.done_button)?.setOnClickListener {
Loading