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

Commit f021cda0 authored by Michal Brzezinski's avatar Michal Brzezinski Committed by Michał Brzeziński
Browse files

Adding UI for sticky keys indicator

Adds:
- coordinator that collects ViewModel and decides if dialog should be shown or hidden + its unit test
- view implementation in Compose: StickyKeysIndicator
- fake implementation for StickyKeysRepository
- fake of KeyboardRespository to Kosmos for easy reuse

Starting of coordinator + its flag will be added in the follow-up change.

Bug: 313855932
Test: StickyKeysIndicatorCoordinatorTest
Flag: N/A - code is not reachable yet
Change-Id: I704346f1b81d1a90ab2ab3141752f2c58e20ac38
parent 5eb91a69
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

package com.android.systemui.compose

import android.app.Dialog
import android.content.Context
import android.view.View
import android.view.WindowInsets
@@ -26,11 +27,13 @@ import com.android.systemui.bouncer.ui.BouncerDialogFactory
import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.StateFlow

@@ -78,6 +81,13 @@ object ComposeFacade : BaseComposeFacade {
        throwComposeUnavailableError()
    }

    override fun createStickyKeysDialog(
        dialogFactory: SystemUIDialogFactory,
        viewModel: StickyKeysIndicatorViewModel
    ): Dialog {
        throwComposeUnavailableError()
    }

    override fun createCommunalView(
        context: Context,
        viewModel: BaseCommunalViewModel,
+12 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.compose

import android.app.Dialog
import android.content.Context
import android.graphics.Point
import android.view.View
@@ -38,6 +39,8 @@ import com.android.systemui.communal.ui.compose.CommunalContainer
import com.android.systemui.communal.ui.compose.CommunalHub
import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.keyboard.stickykeys.ui.view.StickyKeysIndicator
import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel
import com.android.systemui.people.ui.compose.PeopleScreen
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
import com.android.systemui.qs.footer.ui.compose.FooterActions
@@ -47,6 +50,8 @@ import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.ui.composable.ComposableScene
import com.android.systemui.scene.ui.composable.SceneContainer
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import com.android.systemui.statusbar.phone.create
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -120,6 +125,13 @@ object ComposeFacade : BaseComposeFacade {
        }
    }

    override fun createStickyKeysDialog(
        dialogFactory: SystemUIDialogFactory,
        viewModel: StickyKeysIndicatorViewModel
    ): Dialog {
        return dialogFactory.create { StickyKeysIndicator(viewModel) }
    }

    override fun createCommunalView(
        context: Context,
        viewModel: BaseCommunalViewModel,
+63 −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.keyboard.stickykeys.ui.view

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.android.systemui.keyboard.stickykeys.shared.model.Locked
import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey
import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel

@Composable
fun StickyKeysIndicator(viewModel: StickyKeysIndicatorViewModel) {
    val stickyKeys by viewModel.indicatorContent.collectAsState(emptyMap())
    StickyKeysIndicator(stickyKeys)
}

@Composable
fun StickyKeysIndicator(stickyKeys: Map<ModifierKey, Locked>, modifier: Modifier = Modifier) {
    Surface(
        color = MaterialTheme.colorScheme.surface,
        shape = MaterialTheme.shapes.medium,
        modifier = modifier
    ) {
        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            modifier = Modifier.padding(16.dp)
        ) {
            stickyKeys.forEach { (key, isLocked) ->
                key(key) {
                    Text(
                        text = key.text,
                        fontWeight = if (isLocked.locked) FontWeight.Bold else FontWeight.Normal
                    )
                }
            }
        }
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

package com.android.systemui.compose

import android.app.Dialog
import android.content.Context
import android.view.View
import android.view.WindowInsets
@@ -26,11 +27,13 @@ import com.android.systemui.bouncer.ui.BouncerDialogFactory
import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.StateFlow

@@ -86,6 +89,12 @@ interface BaseComposeFacade {
        sceneByKey: Map<SceneKey, Scene>,
    ): View

    /** Creates sticky key dialog presenting provided [viewModel] **/
    fun createStickyKeysDialog(
        dialogFactory: SystemUIDialogFactory,
        viewModel: StickyKeysIndicatorViewModel
    ): Dialog

    /** Create a [View] to represent [viewModel] on screen. */
    fun createCommunalView(
        context: Context,
+11 −2
Original line number Diff line number Diff line
@@ -26,11 +26,20 @@ import javax.inject.Inject
private const val TAG = "stickyKeys"

class StickyKeysLogger @Inject constructor(@KeyboardLog private val buffer: LogBuffer) {
    fun logNewStickyKeysReceived(linkedHashMap: Map<ModifierKey, Locked>) {
    fun logNewStickyKeysReceived(stickyKeys: Map<ModifierKey, Locked>) {
        buffer.log(
            TAG,
            LogLevel.VERBOSE,
            { str1 = linkedHashMap.toString() },
            { str1 = stickyKeys.toString() },
            { "new sticky keys state received: $str1" }
        )
    }

    fun logNewUiState(stickyKeys: Map<ModifierKey, Locked>) {
        buffer.log(
            TAG,
            LogLevel.INFO,
            { str1 = stickyKeys.toString() },
            { "new sticky keys state received: $str1" }
        )
    }
Loading