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

Commit ef8f854a authored by Alejandro Nijamkin's avatar Alejandro Nijamkin Committed by Android (Google) Code Review
Browse files

Merge "Moves quick affordances into domain layer." into tm-qpr-dev

parents 2701e807 6b4f8b1a
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -6,16 +6,16 @@ credit card, etc.

## Adding a new Quick Affordance
### Step 1: create a new quick affordance config
* Create a new class under the [systemui/keyguard/data/quickaffordance](../../src/com/android/systemui/keyguard/data/quickaffordance) directory
* Create a new class under the [systemui/keyguard/domain/quickaffordance](../../src/com/android/systemui/keyguard/domain/quickaffordance) directory
* Please make sure that the class is injected through the Dagger dependency injection system by using the `@Inject` annotation on its main constructor and the `@SysUISingleton` annotation at class level, to make sure only one instance of the class is ever instantiated
* Have the class implement the [KeyguardQuickAffordanceConfig](../../src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt) interface, notes:
* Have the class implement the [KeyguardQuickAffordanceConfig](../../src/com/android/systemui/keyguard/domain/quickaffordance/KeyguardQuickAffordanceConfig.kt) interface, notes:
  * The `state` Flow property must emit `State.Hidden` when the feature is not enabled!
  * It is safe to assume that `onQuickAffordanceClicked` will not be invoked if-and-only-if the previous rule is followed
  * When implementing `onQuickAffordanceClicked`, the implementation can do something or it can ask the framework to start an activity using an `Intent` provided by the implementation
* Please include a unit test for your new implementation under [the correct directory](../../tests/src/com/android/systemui/keyguard/data/quickaffordance)
* Please include a unit test for your new implementation under [the correct directory](../../tests/src/com/android/systemui/keyguard/domain/quickaffordance)

### Step 2: choose a position and priority
* Add the new class as a dependency in the constructor of [KeyguardQuickAffordanceConfigs](../../src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceConfigs.kt)
* Add the new class as a dependency in the constructor of [KeyguardQuickAffordanceRegistry](../../src/com/android/systemui/keyguard/domain/quickaffordance/KeyguardQuickAffordanceRegistry.kt)
* Place the new class in one of the available positions in the `configsByPosition` property, note:
  * In each position, there is a list. The order matters. The order of that list is the priority order in which the framework considers each config. The first config whose state property returns `State.Visible` determines the button that is shown for that position
  * Please only add to one position. The framework treats each position individually and there is no good way to prevent the same config from making its button appear in more than one position at the same time
+2 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.data.repository.KeyguardRepositoryModule;
import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceModule;
import com.android.systemui.keyguard.domain.usecase.KeyguardUseCaseModule;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.statusbar.NotificationShadeDepthController;
@@ -70,6 +71,7 @@ import dagger.Provides;
        KeyguardUserSwitcherComponent.class},
        includes = {
            FalsingModule.class,
            KeyguardQuickAffordanceModule.class,
            KeyguardRepositoryModule.class,
            KeyguardUseCaseModule.class,
        })
+0 −65
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.keyguard.data.repository

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.config.KeyguardQuickAffordanceConfigs
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.State
import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordanceModel
import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePosition
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine

/** Defines interface for classes that encapsulate quick affordance state for the keyguard. */
interface KeyguardQuickAffordanceRepository {
    fun affordance(position: KeyguardQuickAffordancePosition): Flow<KeyguardQuickAffordanceModel>
}

/** Real implementation of [KeyguardQuickAffordanceRepository] */
@SysUISingleton
class KeyguardQuickAffordanceRepositoryImpl
@Inject
constructor(
    private val configs: KeyguardQuickAffordanceConfigs,
) : KeyguardQuickAffordanceRepository {

    /** Returns an observable for the quick affordance model in the given position. */
    override fun affordance(
        position: KeyguardQuickAffordancePosition
    ): Flow<KeyguardQuickAffordanceModel> {
        val configs = configs.getAll(position)
        return combine(configs.map { config -> config.state }) { states ->
            val index = states.indexOfFirst { state -> state is State.Visible }
            val visibleState =
                if (index != -1) {
                    states[index] as State.Visible
                } else {
                    null
                }
            if (visibleState != null) {
                KeyguardQuickAffordanceModel.Visible(
                    configKey = configs[index]::class,
                    icon = visibleState.icon,
                    contentDescriptionResourceId = visibleState.contentDescriptionResourceId,
                )
            } else {
                KeyguardQuickAffordanceModel.Hidden
            }
        }
    }
}
+0 −12
Original line number Diff line number Diff line
@@ -16,22 +16,10 @@

package com.android.systemui.keyguard.data.repository

import com.android.systemui.keyguard.data.config.KeyguardQuickAffordanceConfigs
import com.android.systemui.keyguard.data.config.KeyguardQuickAffordanceConfigsImpl
import dagger.Binds
import dagger.Module

@Module
interface KeyguardRepositoryModule {
    @Binds fun keyguardRepository(impl: KeyguardRepositoryImpl): KeyguardRepository

    @Binds
    fun keyguardQuickAffordanceRepository(
        impl: KeyguardQuickAffordanceRepositoryImpl
    ): KeyguardQuickAffordanceRepository

    @Binds
    fun keyguardQuickAffordanceConfigs(
        impl: KeyguardQuickAffordanceConfigsImpl
    ): KeyguardQuickAffordanceConfigs
}
+19 −3
Original line number Diff line number Diff line
@@ -15,11 +15,11 @@
 *
 */

package com.android.systemui.keyguard.shared.model
package com.android.systemui.keyguard.domain.model

import androidx.annotation.StringRes
import com.android.systemui.containeddrawable.ContainedDrawable
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceConfig
import kotlin.reflect.KClass

/**
@@ -27,7 +27,6 @@ import kotlin.reflect.KClass
 * lock-screen).
 */
sealed class KeyguardQuickAffordanceModel {

    /** No affordance should show up. */
    object Hidden : KeyguardQuickAffordanceModel()

@@ -43,4 +42,21 @@ sealed class KeyguardQuickAffordanceModel {
         */
        @StringRes val contentDescriptionResourceId: Int,
    ) : KeyguardQuickAffordanceModel()

    companion object {
        fun from(
            state: KeyguardQuickAffordanceConfig.State?,
            configKey: KClass<out KeyguardQuickAffordanceConfig>,
        ): KeyguardQuickAffordanceModel {
            return when (state) {
                is KeyguardQuickAffordanceConfig.State.Visible ->
                    Visible(
                        configKey = configKey,
                        icon = state.icon,
                        contentDescriptionResourceId = state.contentDescriptionResourceId,
                    )
                else -> Hidden
            }
        }
    }
}
Loading