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

Commit 0ebc865c authored by Matías Hernández's avatar Matías Hernández
Browse files

Show icons for apps bypassing DND

(Several things pending, such as the +n icon and the correct pending icons, but it's a start).

Test: atest com.android.settings.notification.modes
Bug: 346551087
Flag: android.app.modes_ui
Change-Id: Ifd2ab6a8bb447739dc8ffe400c3960779d477fd6
parent fe712d3e
Loading
Loading
Loading
Loading
+84 −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.
  -->

<!-- Based off preference_two_target.xml, with the added LinearLayout for the icons. -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
    android:gravity="center_vertical"
    android:background="?android:attr/selectableItemBackground"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:clipToPadding="false">

    <include layout="@layout/settingslib_icon_frame"/>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:paddingTop="16dp"
        android:paddingBottom="16dp">

        <TextView
            android:id="@android:id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLines="2"
            android:hyphenationFrequency="normalFast"
            android:lineBreakWordStyle="phrase"
            android:textAppearance="?android:attr/textAppearanceListItem"
            android:ellipsize="marquee"/>

        <TextView
            android:id="@android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@android:id/title"
            android:layout_alignStart="@android:id/title"
            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
            android:textColor="?android:attr/textColorSecondary"
            android:hyphenationFrequency="normalFast"
            android:lineBreakWordStyle="phrase"
            android:maxLines="10"/>

        <!-- Circular icons (32dp) will be ImageViews under this LinearLayout -->
        <LinearLayout
            android:id="@+id/circles_container"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_below="@android:id/summary"
            android:layout_alignStart="@android:id/title" />

    </RelativeLayout>

    <include layout="@layout/preference_two_target_divider" />

    <!-- Preference should place its actual preference widget here. -->
    <LinearLayout
        android:id="@android:id/widget_frame"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:minWidth="@dimen/two_target_min_width"
        android:gravity="center"
        android:orientation="vertical" />

</LinearLayout>
+24 −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.
  -->

<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@dimen/zen_mode_circular_icon_size"
    android:layout_height="@dimen/zen_mode_circular_icon_size"
    android:layout_marginTop="@dimen/zen_mode_circular_icon_margin_vertical"
    android:layout_marginBottom="@dimen/zen_mode_circular_icon_margin_vertical"
    android:layout_marginEnd="@dimen/zen_mode_circular_icon_margin_between" />
 No newline at end of file
+4 −0
Original line number Diff line number Diff line
@@ -508,4 +508,8 @@
    <dimen name="zen_mode_icon_list_item_size">96dp</dimen>
    <dimen name="zen_mode_icon_list_item_circle_diameter">56dp</dimen>
    <dimen name="zen_mode_icon_list_item_icon_size">32dp</dimen>
    <!-- For the items in the CircularIconsPreference (contacts, apps, sound channels). -->
    <dimen name="zen_mode_circular_icon_size">32dp</dimen>
    <dimen name="zen_mode_circular_icon_margin_between">4dp</dimen>
    <dimen name="zen_mode_circular_icon_margin_vertical">8dp</dimen>
</resources>
+8 −8
Original line number Diff line number Diff line
@@ -36,15 +36,15 @@
            android:key="allow_filtering"
            android:title="@string/mode_notification_filter_title"/>

        <Preference
        <com.android.settings.notification.modes.CircularIconsPreference
            android:key="zen_mode_people"
            android:title="@string/zen_category_people" />

        <Preference
        <com.android.settings.notification.modes.CircularIconsPreference
            android:key="zen_mode_apps"
            android:title="@string/zen_category_apps" />

        <Preference
        <com.android.settings.notification.modes.CircularIconsPreference
            android:key="zen_other_settings"
            android:title="@string/zen_category_exceptions" />
    </PreferenceCategory>
+98 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

package com.android.settings.notification.modes;

import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;

import androidx.annotation.VisibleForTesting;

import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;

/**
 * A set of icons to be displayed in a {@link CircularIconsPreference}
 *
 * @param <T> The type of the items in the set. Can be an arbitrary type, the only requirement
 *           being that the {@code drawableLoader} supplied to the constructor is able to produce
 *           a {@link Drawable} from it (for example a resource id, a Content Uri, etc).
 */
class CircularIconSet<T> {

    @VisibleForTesting // Can be set by tests, before creating instances.
    static ExecutorService sExecutorService = Executors.newCachedThreadPool();

    static final CircularIconSet<?> EMPTY = new CircularIconSet<>(ImmutableList.of(),
            unused -> new ColorDrawable(Color.BLACK));

    private final ImmutableList<T> mItems;
    private final Function<T, Drawable> mDrawableLoader;
    private final ListeningExecutorService mBackgroundExecutor;

    private final ConcurrentHashMap<T, Drawable> mCachedIcons;

    CircularIconSet(List<T> items, Function<T, Drawable> drawableLoader) {
        mItems = ImmutableList.copyOf(items);
        mDrawableLoader = drawableLoader;
        mBackgroundExecutor = MoreExecutors.listeningDecorator(sExecutorService);
        mCachedIcons = new ConcurrentHashMap<>();
    }

    int size() {
        return mItems.size();
    }

    /**
     * Loads all icons from the set, using the supplied {@code drawableLoader}, in a background
     * thread.
     */
    List<ListenableFuture<Drawable>> getIcons() {
        return getIcons(Integer.MAX_VALUE);
    }

    /**
     * Loads up to {@code maxSize} icons from the set, using the supplied {@code drawableLoader}, in
     * a background thread.
     */
    List<ListenableFuture<Drawable>> getIcons(int maxNumber) {
        return mItems.stream().limit(maxNumber)
                .map(this::loadIcon)
                .toList();
    }

    private ListenableFuture<Drawable> loadIcon(T item) {
        return mBackgroundExecutor.submit(() -> {
            if (mCachedIcons.containsKey(item)) {
                return mCachedIcons.get(item);
            }
            Drawable drawable = mDrawableLoader.apply(item);
            if (drawable != null) {
                mCachedIcons.put(item, drawable);
            }
            return drawable;
        });
    }
}
Loading