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

Commit d3057f0d authored by Julia Tuttle's avatar Julia Tuttle Committed by Android (Google) Code Review
Browse files

Merge "Add promoted notification ViewModel and (AOD) Interactor" into main

parents a8f95457 34103146
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.notification.promoted
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel.ERROR
import com.android.systemui.log.core.LogLevel.INFO
import com.android.systemui.log.dagger.NotificationLog
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
@@ -27,7 +26,7 @@ import javax.inject.Inject

class PromotedNotificationLogger
@Inject
constructor(@NotificationLog private val buffer: LogBuffer) {
constructor(@PromotedNotificationLog private val buffer: LogBuffer) {
    fun logExtractionSkipped(entry: NotificationEntry, reason: String) {
        buffer.log(
            EXTRACTION_TAG,
+34 −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.systemui.statusbar.notification.promoted.domain.interactor

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

@SysUISingleton
class AODPromotedNotificationInteractor
@Inject
constructor(activeNotificationsInteractor: ActiveNotificationsInteractor) {
    val content: Flow<PromotedNotificationContentModel?> =
        activeNotificationsInteractor.topLevelRepresentativeNotifications.map { notifs ->
            notifs.firstNotNullOfOrNull { it.promotedContent }
        }
}
+4 −2
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ import com.android.systemui.statusbar.notification.promoted.PromotedNotification
 * like the skeleton view on AOD or the status bar chip.
 */
data class PromotedNotificationContentModel(
    val key: String,
    val identity: Identity,

    // for all styles:
    val skeletonSmallIcon: Icon?, // TODO(b/377568176): Make into an IconModel.
@@ -82,7 +82,7 @@ data class PromotedNotificationContentModel(

        fun build() =
            PromotedNotificationContentModel(
                key = key,
                identity = Identity(key, style),
                skeletonSmallIcon = skeletonSmallIcon,
                appName = appName,
                subText = subText,
@@ -103,6 +103,8 @@ data class PromotedNotificationContentModel(
            )
    }

    data class Identity(val key: String, val style: Style)

    /** The timestamp associated with a notification, along with the mode used to display it. */
    data class When(val time: Long, val mode: Mode) {
        /** The mode used to display a notification's `when` value. */
+46 −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.systemui.statusbar.notification.promoted.ui.viewmodel

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.notification.promoted.domain.interactor.AODPromotedNotificationInteractor
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Identity
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map

@SysUISingleton
class AODPromotedNotificationViewModel
@Inject
constructor(interactor: AODPromotedNotificationInteractor) {
    private val content: Flow<PromotedNotificationContentModel?> = interactor.content
    private val identity: Flow<Identity?> = content.mapNonNullsKeepingNulls { it.identity }

    val notification: Flow<PromotedNotificationViewModel?> =
        identity.distinctUntilChanged().mapNonNullsKeepingNulls { identity ->
            val updates = interactor.content.filterNotNull().filter { it.identity == identity }
            PromotedNotificationViewModel(identity, updates)
        }
}

private fun <T, R> Flow<T?>.mapNonNullsKeepingNulls(block: (T) -> R): Flow<R?> = map {
    it?.let(block)
}
+58 −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.systemui.statusbar.notification.promoted.ui.viewmodel

import android.graphics.drawable.Icon
import com.android.internal.widget.NotificationProgressModel
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style
import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.When
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

class PromotedNotificationViewModel(
    identity: PromotedNotificationContentModel.Identity,
    content: Flow<PromotedNotificationContentModel>,
) {
    // for all styles:

    val key: String = identity.key
    val style: Style = identity.style

    val skeletonSmallIcon: Flow<Icon?> = content.map { it.skeletonSmallIcon }
    val appName: Flow<CharSequence?> = content.map { it.appName }
    val subText: Flow<CharSequence?> = content.map { it.subText }

    private val time: Flow<When?> = content.map { it.time }
    val whenTime: Flow<Long?> = time.map { it?.time }
    val whenMode: Flow<When.Mode?> = time.map { it?.mode }

    val lastAudiblyAlertedMs: Flow<Long> = content.map { it.lastAudiblyAlertedMs }
    val profileBadgeResId: Flow<Int?> = content.map { it.profileBadgeResId }
    val title: Flow<CharSequence?> = content.map { it.title }
    val text: Flow<CharSequence?> = content.map { it.text }
    val skeletonLargeIcon: Flow<Icon?> = content.map { it.skeletonLargeIcon }

    // for CallStyle:
    val personIcon: Flow<Icon?> = content.map { it.personIcon }
    val personName: Flow<CharSequence?> = content.map { it.personName }
    val verificationIcon: Flow<Icon?> = content.map { it.verificationIcon }
    val verificationText: Flow<CharSequence?> = content.map { it.verificationText }

    // for ProgressStyle:
    val progress: Flow<NotificationProgressModel?> = content.map { it.progress }
}