diff --git a/auth/composables/api/current.api b/auth/composables/api/current.api index 25fb658f49..5d104e8495 100644 --- a/auth/composables/api/current.api +++ b/auth/composables/api/current.api @@ -1,6 +1,11 @@ // Signature format: 4.0 package com.google.android.horologist.auth.composables.chips { + public final class AccountChipKt { + method @androidx.compose.runtime.Composable public static void AccountChip(com.google.android.horologist.auth.composables.model.AccountUiModel account, kotlin.jvm.functions.Function0 onClick, optional androidx.compose.ui.Modifier modifier, optional Object? defaultAvatar, optional boolean largeAvatar, optional androidx.compose.ui.graphics.painter.Painter? placeholder, optional androidx.wear.compose.material.ChipColors colors, optional boolean enabled); + method @androidx.compose.runtime.Composable public static void AccountChip(String email, kotlin.jvm.functions.Function0 onClick, optional androidx.compose.ui.Modifier modifier, optional Object? avatar, optional Object? defaultAvatar, optional boolean largeAvatar, optional androidx.compose.ui.graphics.painter.Painter? placeholder, optional androidx.wear.compose.material.ChipColors colors, optional boolean enabled); + } + public final class CreateAccountChipKt { method @androidx.compose.runtime.Composable public static void CreateAccountChip(kotlin.jvm.functions.Function0 onClick, optional androidx.compose.ui.Modifier modifier, optional String label, optional boolean largeIconSpace, optional androidx.wear.compose.material.ChipColors colors, optional boolean enabled); } diff --git a/auth/composables/src/debug/java/com/google/android/horologist/auth/composables/chips/AccountChipPreview.kt b/auth/composables/src/debug/java/com/google/android/horologist/auth/composables/chips/AccountChipPreview.kt new file mode 100644 index 0000000000..9fd0972c10 --- /dev/null +++ b/auth/composables/src/debug/java/com/google/android/horologist/auth/composables/chips/AccountChipPreview.kt @@ -0,0 +1,45 @@ +/* + * 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.auth.composables.chips + +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview + +@Preview( + backgroundColor = 0xff000000, + showBackground = true +) +@Composable +fun AccountChipPreview() { + AccountChip( + email = "maggie@example.com", + onClick = {} + ) +} + +@Preview( + backgroundColor = 0xff000000, + showBackground = true +) +@Composable +fun AccountChipPreviewNoAvatar() { + AccountChip( + email = "maggie@example.com", + onClick = {}, + defaultAvatar = null + ) +} diff --git a/auth/composables/src/main/java/com/google/android/horologist/auth/composables/chips/AccountChip.kt b/auth/composables/src/main/java/com/google/android/horologist/auth/composables/chips/AccountChip.kt new file mode 100644 index 0000000000..5bb27b5eea --- /dev/null +++ b/auth/composables/src/main/java/com/google/android/horologist/auth/composables/chips/AccountChip.kt @@ -0,0 +1,99 @@ +/* + * 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.auth.composables.chips + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccountCircle +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.text.style.LineBreak +import androidx.wear.compose.material.ChipColors +import androidx.wear.compose.material.ChipDefaults +import androidx.wear.compose.material.MaterialTheme +import com.google.android.horologist.auth.composables.model.AccountUiModel +import com.google.android.horologist.compose.material.Chip + +/** + * A [Chip] to display the [AccountUiModel]'s email address and avatar. + * + * The email text has optimised line break parameters, in order to display as much text as it can. + */ +@Composable +public fun AccountChip( + account: AccountUiModel, + onClick: () -> Unit, + modifier: Modifier = Modifier, + defaultAvatar: Any? = Icons.Default.AccountCircle, + largeAvatar: Boolean = true, + placeholder: Painter? = null, + colors: ChipColors = ChipDefaults.primaryChipColors(), + enabled: Boolean = true +) { + AccountChip( + email = account.email, + onClick = onClick, + modifier = modifier, + avatar = account.avatar, + defaultAvatar = defaultAvatar, + largeAvatar = largeAvatar, + placeholder = placeholder, + colors = colors, + enabled = enabled + ) +} + +/** + * A [Chip] to display an email address and avatar. + * + * The email text has optimised line break parameters, in order to display as much text as it can. + */ +@Composable +public fun AccountChip( + email: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, + avatar: Any? = null, + defaultAvatar: Any? = Icons.Default.AccountCircle, + largeAvatar: Boolean = true, + placeholder: Painter? = null, + colors: ChipColors = ChipDefaults.primaryChipColors(), + enabled: Boolean = true +) { + MaterialTheme( + typography = MaterialTheme.typography.copy( + button = MaterialTheme.typography.button.copy( + lineBreak = LineBreak( + strategy = LineBreak.Strategy.Balanced, + strictness = LineBreak.Strictness.Normal, + wordBreak = LineBreak.WordBreak.Default + ) + ) + ) + ) { + Chip( + label = email, + onClick = onClick, + modifier = modifier, + icon = avatar ?: defaultAvatar, + largeIcon = largeAvatar, + placeholder = placeholder, + colors = colors, + enabled = enabled + ) + } +} diff --git a/auth/composables/src/main/java/com/google/android/horologist/auth/composables/screens/SelectAccountScreen.kt b/auth/composables/src/main/java/com/google/android/horologist/auth/composables/screens/SelectAccountScreen.kt index 513040d231..a1abced973 100644 --- a/auth/composables/src/main/java/com/google/android/horologist/auth/composables/screens/SelectAccountScreen.kt +++ b/auth/composables/src/main/java/com/google/android/horologist/auth/composables/screens/SelectAccountScreen.kt @@ -24,13 +24,15 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.LineBreak import androidx.compose.ui.unit.dp import androidx.wear.compose.material.ChipDefaults +import androidx.wear.compose.material.MaterialTheme import com.google.android.horologist.auth.composables.R +import com.google.android.horologist.auth.composables.chips.AccountChip import com.google.android.horologist.auth.composables.model.AccountUiModel import com.google.android.horologist.compose.layout.ScalingLazyColumn import com.google.android.horologist.compose.layout.ScalingLazyColumnState -import com.google.android.horologist.compose.material.Chip import com.google.android.horologist.compose.material.Title private const val HORIZONTAL_PADDING_SCREEN_PERCENTAGE = 0.052 @@ -62,14 +64,24 @@ public fun SelectAccountScreen( items(accounts.size) { index -> val account = accounts[index] - - Chip( - label = account.email, - icon = account.avatar ?: defaultAvatar, - largeIcon = true, - onClick = { onAccountClicked(index, account) }, - colors = ChipDefaults.secondaryChipColors() - ) + MaterialTheme( + typography = MaterialTheme.typography.copy( + button = MaterialTheme.typography.button.copy( + lineBreak = LineBreak( + strategy = LineBreak.Strategy.Balanced, + strictness = LineBreak.Strictness.Normal, + wordBreak = LineBreak.WordBreak.Default + ) + ) + ) + ) { + AccountChip( + account = account, + onClick = { onAccountClicked(index, account) }, + colors = ChipDefaults.secondaryChipColors(), + defaultAvatar = defaultAvatar + ) + } } } } diff --git a/auth/composables/src/test/java/com/google/android/horologist/auth/composables/chips/AccountChipTest.kt b/auth/composables/src/test/java/com/google/android/horologist/auth/composables/chips/AccountChipTest.kt new file mode 100644 index 0000000000..01201bdd36 --- /dev/null +++ b/auth/composables/src/test/java/com/google/android/horologist/auth/composables/chips/AccountChipTest.kt @@ -0,0 +1,87 @@ +/* + * 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.auth.composables.chips + +import androidx.wear.compose.material.ChipDefaults +import com.google.android.horologist.screenshots.ScreenshotBaseTest +import org.junit.Test + +class AccountChipTest : ScreenshotBaseTest() { + + @Test + fun default() { + screenshotTestRule.setContent(isComponent = true, takeScreenshot = true) { + AccountChip( + email = "maggie@example.com", + onClick = {} + ) + } + } + + @Test + fun disabled() { + screenshotTestRule.setContent(isComponent = true, takeScreenshot = true) { + AccountChip( + email = "maggie@example.com", + onClick = {}, + enabled = false + ) + } + } + + @Test + fun withSmallAvatar() { + screenshotTestRule.setContent(isComponent = true, takeScreenshot = true) { + AccountChip( + email = "maggie@example.com", + onClick = {}, + largeAvatar = false + ) + } + } + + @Test + fun withSecondaryChipType() { + screenshotTestRule.setContent(isComponent = true, takeScreenshot = true) { + AccountChip( + email = "maggie@example.com", + onClick = {}, + colors = ChipDefaults.secondaryChipColors() + ) + } + } + + @Test + fun withLongEmailAddress() { + screenshotTestRule.setContent(isComponent = true, takeScreenshot = true) { + AccountChip( + email = "thisisaverylongemailaddresssample@example.com", + onClick = {} + ) + } + } + + @Test + fun withEmailAddressStartingWithSingleLetterAndDot() { + screenshotTestRule.setContent(isComponent = true, takeScreenshot = true) { + AccountChip( + email = "p.thisisaverylongemailaddress@example.com", + onClick = {} + ) + } + } +} diff --git a/auth/composables/src/test/java/com/google/android/horologist/auth/composables/chips/CreateAccountChipTest.kt b/auth/composables/src/test/java/com/google/android/horologist/auth/composables/chips/CreateAccountChipTest.kt index 7e7c723b2a..1ad4a0ff8d 100644 --- a/auth/composables/src/test/java/com/google/android/horologist/auth/composables/chips/CreateAccountChipTest.kt +++ b/auth/composables/src/test/java/com/google/android/horologist/auth/composables/chips/CreateAccountChipTest.kt @@ -44,9 +44,7 @@ class CreateAccountChipTest : ScreenshotBaseTest() { screenshotTestRule.setContent(isComponent = true, takeScreenshot = true) { CreateAccountChip( onClick = {}, - largeIconSpace = true, - colors = ChipDefaults.secondaryChipColors(), - enabled = false + largeIconSpace = true ) } } diff --git a/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_default.png b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_default.png new file mode 100644 index 0000000000..37eefa3981 --- /dev/null +++ b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d6456b7e1bdadab78724b066925f3ca53a5f7faaa82aa1734a00d92682704172 +size 10854 diff --git a/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_disabled.png b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_disabled.png new file mode 100644 index 0000000000..baf00609e1 --- /dev/null +++ b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_disabled.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89ed7ddf8238ec3204aa4277bf661cb05762ac3aac48857097f058201ed10176 +size 11841 diff --git a/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withEmailAddressStartingWithSingleLetterAndDot.png b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withEmailAddressStartingWithSingleLetterAndDot.png new file mode 100644 index 0000000000..19431da72f --- /dev/null +++ b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withEmailAddressStartingWithSingleLetterAndDot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd91b04ed5b22b38d767d2c7e6775f36515792e47004c10a788b6866e91ce1b0 +size 15981 diff --git a/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withLongEmailAddress.png b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withLongEmailAddress.png new file mode 100644 index 0000000000..5c523140fd --- /dev/null +++ b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withLongEmailAddress.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e3a800507435367bba07a90f31dca97dc29238e6c22e90ff16d77f33074cfd8 +size 15871 diff --git a/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withSecondaryChipType.png b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withSecondaryChipType.png new file mode 100644 index 0000000000..ac41b6af80 --- /dev/null +++ b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withSecondaryChipType.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1a1e2e88bd8970ae67fbd0b8add4a7b0d3b5dfe56709f17f477bfc09553529c +size 10676 diff --git a/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withSmallAvatar.png b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withSmallAvatar.png new file mode 100644 index 0000000000..ca70e1e8dd --- /dev/null +++ b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_AccountChipTest_withSmallAvatar.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4f22511ebe03479bdf0c0241787f69fe494e4f9b6f230b654171b167929f333 +size 10333 diff --git a/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_CreateAccountChipTest_withLargeIconSpace.png b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_CreateAccountChipTest_withLargeIconSpace.png index 5341727d42..1dea6fc581 100644 --- a/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_CreateAccountChipTest_withLargeIconSpace.png +++ b/auth/composables/src/test/snapshots/images/com.google.android.horologist.auth.composables.chips_CreateAccountChipTest_withLargeIconSpace.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae2c47d5aa0f5dfb77eca5b02b91c5c54d2292051bdeba68fd9f7ddac3828ad5 -size 7378 +oid sha256:1e9d3b817d33dea6529a03fe3900608b1040170c5e173ef38a414af8f597698f +size 7536 diff --git a/compose-material/src/main/java/com/google/android/horologist/compose/material/Chip.kt b/compose-material/src/main/java/com/google/android/horologist/compose/material/Chip.kt index 46605307db..7cabe98e09 100644 --- a/compose-material/src/main/java/com/google/android/horologist/compose/material/Chip.kt +++ b/compose-material/src/main/java/com/google/android/horologist/compose/material/Chip.kt @@ -41,7 +41,6 @@ import androidx.wear.compose.material.ChipColors import androidx.wear.compose.material.ChipDefaults import androidx.wear.compose.material.Icon import androidx.wear.compose.material.LocalContentAlpha -import androidx.wear.compose.material.MaterialTheme import androidx.wear.compose.material.Text import coil.compose.rememberAsyncImagePainter import com.google.android.horologist.annotations.ExperimentalHorologistApi @@ -180,8 +179,7 @@ public fun Chip( modifier = Modifier.fillMaxWidth(), textAlign = if (hasSecondaryLabel || hasIcon) TextAlign.Start else TextAlign.Center, overflow = TextOverflow.Ellipsis, - maxLines = if (hasSecondaryLabel) 1 else 2, - style = MaterialTheme.typography.button + maxLines = if (hasSecondaryLabel) 1 else 2 ) } @@ -191,8 +189,7 @@ public fun Chip( Text( text = secondaryLabel, overflow = TextOverflow.Ellipsis, - maxLines = 1, - style = MaterialTheme.typography.caption2 + maxLines = 1 ) } }