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

Commit e3eb9a1a authored by Gustavo Pagani's avatar Gustavo Pagani
Browse files

Add single provider and single account screens

Bug: 301206470
Test: N/A - feature not fully implemented yet

Change-Id: I25f54e2bcb8228b46a8ca7a89f63753c639a26ef
parent e10140ee
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ android_library {
        "androidx.compose.foundation_foundation",
        "androidx.compose.runtime_runtime",
        "androidx.compose.ui_ui",
        "androidx.compose.ui_ui-tooling",
        "androidx.navigation_navigation-compose",
        "androidx.lifecycle_lifecycle-extensions",
        "androidx.lifecycle_lifecycle-runtime-ktx",
+26 −0
Original line number Diff line number Diff line
/*
 * Copyright 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
 *
 *      https://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.google.android.horologist.compose.layout

import androidx.compose.runtime.Composable
import com.google.android.horologist.annotations.ExperimentalHorologistApi

@OptIn(ExperimentalHorologistApi::class)
@Composable
public fun belowTimeTextPreview(): ScalingLazyColumnState {
    return ScalingLazyColumnDefaults.belowTimeText().create()
}
+143 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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
 *
 *      https://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.google.android.horologist.compose.material

import androidx.annotation.DrawableRes
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.Dp
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.ButtonColors
import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.ButtonDefaults.DefaultButtonSize
import androidx.wear.compose.material.ButtonDefaults.DefaultIconSize
import androidx.wear.compose.material.ButtonDefaults.LargeButtonSize
import androidx.wear.compose.material.ButtonDefaults.LargeIconSize
import androidx.wear.compose.material.ButtonDefaults.SmallButtonSize
import androidx.wear.compose.material.ButtonDefaults.SmallIconSize
import com.google.android.horologist.annotations.ExperimentalHorologistApi

/**
 * This component is an alternative to [Button], providing the following:
 * - a convenient way of providing an icon and choosing its size from a range of sizes recommended
 * by the Wear guidelines;
 */
@ExperimentalHorologistApi
@Composable
public fun Button(
    imageVector: ImageVector,
    contentDescription: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
    buttonSize: ButtonSize = ButtonSize.Default,
    iconRtlMode: IconRtlMode = IconRtlMode.Default,
    enabled: Boolean = true,
) {
    Button(
        icon = imageVector,
        contentDescription = contentDescription,
        onClick = onClick,
        modifier = modifier,
        colors = colors,
        buttonSize = buttonSize,
        iconRtlMode = iconRtlMode,
        enabled = enabled,
    )
}

/**
 * This component is an alternative to [Button], providing the following:
 * - a convenient way of providing an icon and choosing its size from a range of sizes recommended
 * by the Wear guidelines;
 */
@ExperimentalHorologistApi
@Composable
public fun Button(
    @DrawableRes id: Int,
    contentDescription: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
    buttonSize: ButtonSize = ButtonSize.Default,
    iconRtlMode: IconRtlMode = IconRtlMode.Default,
    enabled: Boolean = true,
) {
    Button(
        icon = id,
        contentDescription = contentDescription,
        onClick = onClick,
        modifier = modifier,
        colors = colors,
        buttonSize = buttonSize,
        iconRtlMode = iconRtlMode,
        enabled = enabled,
    )
}

@OptIn(ExperimentalHorologistApi::class)
@Composable
internal fun Button(
    icon: Any,
    contentDescription: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
    buttonSize: ButtonSize = ButtonSize.Default,
    iconRtlMode: IconRtlMode = IconRtlMode.Default,
    enabled: Boolean = true,
) {
    Button(
        onClick = onClick,
        modifier = modifier.size(buttonSize.tapTargetSize),
        enabled = enabled,
        colors = colors,
    ) {
        val iconModifier = Modifier
            .size(buttonSize.iconSize)
            .align(Alignment.Center)

        Icon(
            icon = icon,
            contentDescription = contentDescription,
            modifier = iconModifier,
            rtlMode = iconRtlMode,
        )
    }
}

@ExperimentalHorologistApi
public sealed class ButtonSize(
    public val iconSize: Dp,
    public val tapTargetSize: Dp,
) {
    public object Default :
        ButtonSize(iconSize = DefaultIconSize, tapTargetSize = DefaultButtonSize)

    public object Large : ButtonSize(iconSize = LargeIconSize, tapTargetSize = LargeButtonSize)
    public object Small : ButtonSize(iconSize = SmallIconSize, tapTargetSize = SmallButtonSize)

    /**
     * Custom sizes should follow the [accessibility principles and guidance for touch targets](https://developer.android.com/training/wearables/accessibility#set-minimum).
     */
    public data class Custom(val customIconSize: Dp, val customTapTargetSize: Dp) :
        ButtonSize(iconSize = customIconSize, tapTargetSize = customTapTargetSize)
}
+129 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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
 *
 *      https://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.google.android.horologist.compose.material

import androidx.annotation.DrawableRes
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.LayoutDirection
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.LocalContentAlpha
import androidx.wear.compose.material.LocalContentColor
import com.google.android.horologist.annotations.ExperimentalHorologistApi

/**
 * This component is an alternative to [Icon], providing the following:
 * - a convenient way of setting the icon to be mirrored in RTL mode;
 */
@ExperimentalHorologistApi
@Composable
public fun Icon(
    imageVector: ImageVector,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current),
    rtlMode: IconRtlMode = IconRtlMode.Default,
) {
    val shouldMirror =
        rtlMode == IconRtlMode.Mirrored && LocalLayoutDirection.current == LayoutDirection.Rtl
    Icon(
        modifier = modifier.scale(
            scaleX = if (shouldMirror) -1f else 1f,
            scaleY = 1f,
        ),
        imageVector = imageVector,
        contentDescription = contentDescription,
        tint = tint,
    )
}

/**
 * This component is an alternative to [Icon], providing the following:
 * - a convenient way of setting the icon to be mirrored in RTL mode;
 */
@ExperimentalHorologistApi
@Composable
public fun Icon(
    @DrawableRes id: Int,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current),
    rtlMode: IconRtlMode = IconRtlMode.Default,
) {
    val shouldMirror =
        rtlMode == IconRtlMode.Mirrored && LocalLayoutDirection.current == LayoutDirection.Rtl

    Icon(
        painter = painterResource(id = id),
        contentDescription = contentDescription,
        modifier = modifier.scale(
            scaleX = if (shouldMirror) -1f else 1f,
            scaleY = 1f,
        ),
        tint = tint,
    )
}

@OptIn(ExperimentalHorologistApi::class)
@Composable
internal fun Icon(
    icon: Any,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current),
    rtlMode: IconRtlMode = IconRtlMode.Default,
) {
    val shouldMirror =
        rtlMode == IconRtlMode.Mirrored && LocalLayoutDirection.current == LayoutDirection.Rtl

    val iconModifier = modifier.scale(
        scaleX = if (shouldMirror) -1f else 1f,
        scaleY = 1f,
    )
    when (icon) {
        is ImageVector -> {
            Icon(
                imageVector = icon,
                modifier = iconModifier,
                contentDescription = contentDescription,
                tint = tint,
            )
        }

        is Int -> {
            Icon(
                painter = painterResource(id = icon),
                contentDescription = contentDescription,
                modifier = iconModifier,
                tint = tint,
            )
        }

        else -> throw IllegalArgumentException("Type not supported.")
    }
}

@ExperimentalHorologistApi
public enum class IconRtlMode {
    Default,
    Mirrored,
}
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright 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
 *
 *      https://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.google.android.horologist.compose.material.util

import com.google.android.horologist.annotations.ExperimentalHorologistApi

/**
 * Make explicit that a conscious decision was made to mark an element as decorative, so it does not
 * have associated actions or state.
 *
 * https://developer.android.com/jetpack/compose/accessibility#describe-visual
 */
@ExperimentalHorologistApi
public val DECORATIVE_ELEMENT_CONTENT_DESCRIPTION: String? = null
Loading