From 61895a6911141aef2aaaae60cf5691291893a19b Mon Sep 17 00:00:00 2001 From: MykytaPimonovTD Date: Thu, 5 Dec 2024 16:53:56 +0200 Subject: [PATCH 1/8] Update versions. --- .../src/main/kotlin/io/spine/internal/dependency/Pingh.kt | 2 +- version.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/desktop/buildSrc/src/main/kotlin/io/spine/internal/dependency/Pingh.kt b/desktop/buildSrc/src/main/kotlin/io/spine/internal/dependency/Pingh.kt index b9a1b998..59534e4d 100644 --- a/desktop/buildSrc/src/main/kotlin/io/spine/internal/dependency/Pingh.kt +++ b/desktop/buildSrc/src/main/kotlin/io/spine/internal/dependency/Pingh.kt @@ -28,7 +28,7 @@ package io.spine.internal.dependency // https://github.com/spine-examples/Pingh public object Pingh { - private const val version = "1.0.0-SNAPSHOT.30" + private const val version = "1.0.0-SNAPSHOT.31" private const val group = "io.spine.examples.pingh" public const val client: String = "$group:client:$version" diff --git a/version.gradle.kts b/version.gradle.kts index 0d857e7a..2e641895 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -27,4 +27,4 @@ /** * The version of the `Pingh` to publish. */ -val pinghVersion: String by extra("1.0.0-SNAPSHOT.30") +val pinghVersion: String by extra("1.0.0-SNAPSHOT.31") From 4f68382f1a2770792e42f1e8d76e0cd96e03de16 Mon Sep 17 00:00:00 2001 From: MykytaPimonovTD Date: Tue, 10 Dec 2024 12:55:15 +0200 Subject: [PATCH 2/8] Animate mentions list. --- .../spine/examples/pingh/desktop/Mentions.kt | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt index 5e4f061c..0e920b24 100644 --- a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt +++ b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt @@ -26,6 +26,9 @@ package io.spine.examples.pingh.desktop +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.VisibilityThreshold +import androidx.compose.animation.core.spring import androidx.compose.foundation.background import androidx.compose.foundation.hoverable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -43,9 +46,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyItemScope import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.verticalScroll import androidx.compose.material3.CardDefaults import androidx.compose.material3.ElevatedCard import androidx.compose.material3.IconButtonDefaults @@ -65,6 +68,7 @@ import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.spine.example.pingh.desktop.generated.resources.Res @@ -177,18 +181,18 @@ private fun MentionCards( flow: MentionsFlow ) { val mentions by flow.mentions.collectAsState() - val scrollState = rememberScrollState() - Column( + val list = remember(mentions) { mentions.sorted() } + LazyColumn( modifier = Modifier .fillMaxSize() .padding(10.dp) - .verticalScroll(scrollState) .background(MaterialTheme.colorScheme.background) .testTag("mention-cards"), verticalArrangement = Arrangement.spacedBy(10.dp) ) { - mentions.sorted() - .forEach { mention -> MentionCard(flow, mention) } + items(list.size, key = { index -> list[index].id }) { index -> + MentionCard(flow, list[index]) + } } } @@ -205,7 +209,7 @@ private fun MentionCards( * @param mention The mention whose information is displayed. */ @Composable -private fun MentionCard( +private fun LazyItemScope.MentionCard( flow: MentionsFlow, mention: MentionView ) { @@ -229,7 +233,12 @@ private fun MentionCard( modifier = Modifier .fillMaxWidth() .testTag("mention-card-${mention.id}") - .height(60.dp), + .height(60.dp) + .animateItem(placementSpec = spring( + dampingRatio = Spring.DampingRatioMediumBouncy, + stiffness = Spring.StiffnessLow, + visibilityThreshold = IntOffset.VisibilityThreshold + )), interactionSource = interactionSource, colors = CardDefaults.elevatedCardColors( containerColor = containerColor, From 214edaec6fafa324a369945eefa84f2f10fd0f71 Mon Sep 17 00:00:00 2001 From: MykytaPimonovTD Date: Tue, 10 Dec 2024 13:34:58 +0200 Subject: [PATCH 3/8] Updated mention card hovered effect. --- .../spine/examples/pingh/desktop/Mentions.kt | 127 +++++++++++++----- 1 file changed, 95 insertions(+), 32 deletions(-) diff --git a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt index 0e920b24..a1f877bf 100644 --- a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt +++ b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt @@ -30,6 +30,7 @@ import androidx.compose.animation.core.Spring import androidx.compose.animation.core.VisibilityThreshold import androidx.compose.animation.core.spring import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.hoverable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsHoveredAsState @@ -49,13 +50,12 @@ import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyItemScope import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ElevatedCard import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember @@ -63,8 +63,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.input.pointer.PointerIcon +import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.style.TextOverflow @@ -82,6 +85,7 @@ import io.spine.examples.pingh.client.howMuchTimeHasPassed import io.spine.examples.pingh.client.sorted import io.spine.examples.pingh.mentions.MentionStatus import io.spine.examples.pingh.mentions.MentionView +import java.awt.Cursor import org.jetbrains.compose.resources.painterResource /** @@ -213,33 +217,33 @@ private fun LazyItemScope.MentionCard( flow: MentionsFlow, mention: MentionView ) { - val uriHandler = LocalUriHandler.current val interactionSource = remember { MutableInteractionSource() } - val isHovered = interactionSource.collectIsHoveredAsState() + val isHovered by interactionSource.collectIsHoveredAsState() val mentionIsRead = mention.status == MentionStatus.READ val containerColor = if (mentionIsRead) { MaterialTheme.colorScheme.onBackground } else { MaterialTheme.colorScheme.secondary } - val onClick = { - uriHandler.openUri(mention.url.spec) - if (!mentionIsRead) { - flow.markAsRead(mention.id) - } - } - ElevatedCard( - onClick = onClick, + val shape = MaterialTheme.shapes.medium + Card( modifier = Modifier .fillMaxWidth() .testTag("mention-card-${mention.id}") .height(60.dp) - .animateItem(placementSpec = spring( - dampingRatio = Spring.DampingRatioMediumBouncy, - stiffness = Spring.StiffnessLow, - visibilityThreshold = IntOffset.VisibilityThreshold - )), - interactionSource = interactionSource, + .shadow( + elevation = if (isHovered) 10.dp else 1.dp, + shape = shape + ) + .hoverable(interactionSource) + .animateItem( + placementSpec = spring( + dampingRatio = Spring.DampingRatioMediumBouncy, + stiffness = Spring.StiffnessLow, + visibilityThreshold = IntOffset.VisibilityThreshold + ) + ), + shape = shape, colors = CardDefaults.elevatedCardColors( containerColor = containerColor, contentColor = MaterialTheme.colorScheme.onSecondary @@ -254,13 +258,13 @@ private fun LazyItemScope.MentionCard( url = mention.whoMentioned.avatarUrl, modifier = Modifier.size(50.dp) ) - MentionCardText(mention, isHovered) + MentionCardText(flow, mention, isHovered) Row( modifier = Modifier.fillMaxHeight(), verticalAlignment = Alignment.CenterVertically ) { - SnoozeButton(flow, mention, isHovered.value) - PinButton(flow, mention, isHovered.value) + SnoozeButton(flow, mention, isHovered) + PinButton(flow, mention, isHovered) } } } @@ -270,28 +274,24 @@ private fun LazyItemScope.MentionCard( * Displays textual information about the mention, * including details about who mentioned the user, where, and when. * + * @param flow The flow for managing the lifecycle of mentions. * @param mention The mention whose information is displayed. - * @param isHovered Indicates whether the mouse is over the mention card. + * @param isParentHovered Indicates whether the mouse is over the mention card. */ @Composable private fun RowScope.MentionCardText( + flow: MentionsFlow, mention: MentionView, - isHovered: State + isParentHovered: Boolean ) { val time = mention.whenMentioned.run { - if (isHovered.value) toDatetime() else howMuchTimeHasPassed() + if (isParentHovered) toDatetime() else howMuchTimeHasPassed() } Column( modifier = Modifier.fillMaxHeight().weight(1f), - verticalArrangement = Arrangement.Center + verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically) ) { - Text( - text = mention.title, - overflow = TextOverflow.Ellipsis, - maxLines = 1, - style = MaterialTheme.typography.bodyLarge - ) - Spacer(Modifier.height(4.dp)) + MentionTitle(flow, mention, isParentHovered) Text( text = "$time, by ${mention.whoMentioned.username.value}", overflow = TextOverflow.Ellipsis, @@ -301,6 +301,69 @@ private fun RowScope.MentionCardText( } } +/** + * Displays a mention header. + * + * Clicking the title navigates to the web page where user was mentioned. + * + * @param flow The flow for managing the lifecycle of mentions. + * @param mention The mention whose information is displayed. + * @param isParentHovered Indicates whether the mouse is over the mention card. + */ +@Composable +private fun MentionTitle( + flow: MentionsFlow, + mention: MentionView, + isParentHovered: Boolean +) { + val uriHandler = LocalUriHandler.current + val readMention = { + uriHandler.openUri(mention.url.spec) + if (mention.status != MentionStatus.READ) { + flow.markAsRead(mention.id) + } + } + val interactionSource = remember { MutableInteractionSource() } + val isHovered by interactionSource.collectIsHoveredAsState() + val color = if (isHovered) { + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.onSecondary + } + Text( + text = mention.title, + modifier = Modifier + .run { + if (isParentHovered) { + drawBehind { + val strokeWidthPx = 1.dp.toPx() + val verticalOffset = size.height - 1.sp.toPx() + drawLine( + color = color, + strokeWidth = strokeWidthPx, + start = Offset(0f, verticalOffset), + end = Offset(size.width, verticalOffset) + ) + } + } else { + this + } + } + .pointerHoverIcon(PointerIcon(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR))) + .hoverable(interactionSource) + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = readMention + ) + .testTag("mention-title"), + color = color, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + style = MaterialTheme.typography.bodyLarge + ) +} + /** * Displays the snooze button if the mention is unread. If the mention is snoozed, * it displays the status text of the mention. From 5a2a790ea49dfa855c56b14928e09bfdded2756a Mon Sep 17 00:00:00 2001 From: MykytaPimonovTD Date: Tue, 10 Dec 2024 14:39:09 +0200 Subject: [PATCH 4/8] Make avatars smaller. --- .../spine/examples/pingh/desktop/Mentions.kt | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt index a1f877bf..1786f987 100644 --- a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt +++ b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt @@ -119,11 +119,13 @@ internal fun MentionsPage( * * @param flow The flow for managing the lifecycle of mentions. * @param toSettingsPage The navigation to the 'Settings' page. + * @param appIconMultiplier The proportion of the button's size that the app icon occupies. */ @Composable private fun ToolBar( flow: MentionsFlow, - toSettingsPage: () -> Unit + toSettingsPage: () -> Unit, + appIconMultiplier: Float = 0.8f ) { val contentColor = MaterialTheme.colorScheme.onSecondary val borderColor = MaterialTheme.colorScheme.onBackground @@ -140,18 +142,19 @@ private fun ToolBar( strokeWidth = 1.dp.toPx() ) } - .padding(start = 27.dp, end = 10.dp), + .padding(start = 20.dp, end = 10.dp), verticalAlignment = Alignment.CenterVertically ) { IconButton( icon = painterResource(Res.drawable.pingh), onClick = toSettingsPage, - modifier = Modifier.size(56.dp).testTag("settings-button"), + modifier = Modifier.size(50.dp).testTag("settings-button"), colors = IconButtonDefaults.iconButtonColors( contentColor = contentColor - ) + ), + sizeMultiplier = appIconMultiplier ) - Spacer(Modifier.width(7.dp)) + Spacer(Modifier.width(5.dp)) Text( text = "Recent mentions", modifier = Modifier.weight(1f), @@ -230,7 +233,7 @@ private fun LazyItemScope.MentionCard( modifier = Modifier .fillMaxWidth() .testTag("mention-card-${mention.id}") - .height(60.dp) + .height(58.dp) .shadow( elevation = if (isHovered) 10.dp else 1.dp, shape = shape @@ -250,13 +253,13 @@ private fun LazyItemScope.MentionCard( ) ) { Row( - modifier = Modifier.padding(start = 20.dp, end = 10.dp), + modifier = Modifier.padding(start = 15.dp, end = 10.dp), horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically ) { Avatar( url = mention.whoMentioned.avatarUrl, - modifier = Modifier.size(50.dp) + modifier = Modifier.size(40.dp) ) MentionCardText(flow, mention, isHovered) Row( From 75bc72fa51172f38e4c1d48cc85f89a3c97f89eb Mon Sep 17 00:00:00 2001 From: MykytaPimonovTD Date: Tue, 10 Dec 2024 16:05:48 +0200 Subject: [PATCH 5/8] Update mention test. --- .../pingh/desktop/MentionsPageUiTest.kt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/desktop/src/test/kotlin/io/spine/examples/pingh/desktop/MentionsPageUiTest.kt b/desktop/src/test/kotlin/io/spine/examples/pingh/desktop/MentionsPageUiTest.kt index b6cc558a..55b5b77c 100644 --- a/desktop/src/test/kotlin/io/spine/examples/pingh/desktop/MentionsPageUiTest.kt +++ b/desktop/src/test/kotlin/io/spine/examples/pingh/desktop/MentionsPageUiTest.kt @@ -30,13 +30,12 @@ import androidx.compose.ui.semantics.SemanticsNode import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.SemanticsNodeInteraction import androidx.compose.ui.test.SemanticsNodeInteractionsProvider -import androidx.compose.ui.test.filter import androidx.compose.ui.test.filterToOne -import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.onChildren import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performScrollToIndex import io.kotest.matchers.floats.shouldBeGreaterThan import io.kotest.matchers.floats.shouldBeLessThan import io.kotest.matchers.ints.shouldBeGreaterThanOrEqual @@ -57,9 +56,9 @@ internal class MentionsPageUiTest : UiTest() { logIn() awaitFact { mentionCards().size shouldBeGreaterThanOrEqual 1 } val tag = mentionCards().random().testTag - onNodeWithTag(tag).performClick() + onTitleWithParentTag(tag).performClick() awaitFact { openedUrlCount() shouldBe 1 } - onNodeWithTag(tag).performClick() + onTitleWithParentTag(tag).performClick() awaitFact { openedUrlCount() shouldBe 2 } } @@ -84,7 +83,7 @@ internal class MentionsPageUiTest : UiTest() { logIn() awaitFact { mentionCards().size shouldBeGreaterThanOrEqual 1 } val tag = mentionCards().random().testTag - onNodeWithTag(tag).performClick() + onTitleWithParentTag(tag).performClick() awaitFact { onNodeWithTag(tag).performHover() onSnoozeButtonWithParentTag(tag).assertDoesNotExist() @@ -102,7 +101,7 @@ internal class MentionsPageUiTest : UiTest() { onNodeWithTag(snoozedMentionTag).performHover() awaitFact { onSnoozeButtonWithParentTag(snoozedMentionTag).assertExists() } onSnoozeButtonWithParentTag(snoozedMentionTag).performClick() - onNodeWithTag(readMentionTag).performClick() + onTitleWithParentTag(readMentionTag).performClick() awaitFact { val mentions = mentionCards() val readMention = mentions.first { it.testTag == readMentionTag } @@ -156,10 +155,16 @@ internal class MentionsPageUiTest : UiTest() { private fun SemanticsNodeInteractionsProvider.mentionCards(): List = onNodeWithTag("mention-cards") + .performScrollToIndex(0) .onChildren() - .filter(hasClickAction()) .fetchSemanticsNodes() + private fun SemanticsNodeInteractionsProvider.onTitleWithParentTag(tag: String): + SemanticsNodeInteraction = + onNodeWithTag(tag) + .onChildren() + .filterToOne(hasTestTag("mention-title")) + private fun SemanticsNodeInteractionsProvider.onSnoozeButtonWithParentTag(tag: String): SemanticsNodeInteraction = onNodeWithTag(tag) From 895b70c2dea92ddcb6ca8cc810897f7bf1f2f6f6 Mon Sep 17 00:00:00 2001 From: MykytaPimonovTD Date: Tue, 10 Dec 2024 17:53:16 +0200 Subject: [PATCH 6/8] Update versions. --- .../src/main/kotlin/io/spine/internal/dependency/Pingh.kt | 2 +- version.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/desktop/buildSrc/src/main/kotlin/io/spine/internal/dependency/Pingh.kt b/desktop/buildSrc/src/main/kotlin/io/spine/internal/dependency/Pingh.kt index 59534e4d..978c83b9 100644 --- a/desktop/buildSrc/src/main/kotlin/io/spine/internal/dependency/Pingh.kt +++ b/desktop/buildSrc/src/main/kotlin/io/spine/internal/dependency/Pingh.kt @@ -28,7 +28,7 @@ package io.spine.internal.dependency // https://github.com/spine-examples/Pingh public object Pingh { - private const val version = "1.0.0-SNAPSHOT.31" + private const val version = "1.0.0-SNAPSHOT.32" private const val group = "io.spine.examples.pingh" public const val client: String = "$group:client:$version" diff --git a/version.gradle.kts b/version.gradle.kts index 2e641895..90a2e0cd 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -27,4 +27,4 @@ /** * The version of the `Pingh` to publish. */ -val pinghVersion: String by extra("1.0.0-SNAPSHOT.31") +val pinghVersion: String by extra("1.0.0-SNAPSHOT.32") From c78a94a70d9b755219221f1f20f30d8e075d8df9 Mon Sep 17 00:00:00 2001 From: MykytaPimonovTD Date: Tue, 10 Dec 2024 18:04:49 +0200 Subject: [PATCH 7/8] Reduce refresh button size. --- .../main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt index 1786f987..dd7aeca9 100644 --- a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt +++ b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt @@ -142,7 +142,7 @@ private fun ToolBar( strokeWidth = 1.dp.toPx() ) } - .padding(start = 20.dp, end = 10.dp), + .padding(start = 20.dp, end = 13.dp), verticalAlignment = Alignment.CenterVertically ) { IconButton( @@ -167,7 +167,7 @@ private fun ToolBar( onClick = { flow.updateMentions() }, - modifier = Modifier.size(50.dp), + modifier = Modifier.size(44.dp), colors = IconButtonDefaults.iconButtonColors( contentColor = contentColor ) From 0e311fcd4425fdcfdc4a6e22f1ceef88b9e8e2bf Mon Sep 17 00:00:00 2001 From: MykytaPimonovTD Date: Tue, 10 Dec 2024 18:31:08 +0200 Subject: [PATCH 8/8] Add static imports and rename variable. --- .../examples/pingh/desktop/IconButton.kt | 17 +++-- .../io/spine/examples/pingh/desktop/Login.kt | 54 ++++++++-------- .../spine/examples/pingh/desktop/Mentions.kt | 62 +++++++++---------- .../examples/pingh/desktop/Navigation.kt | 19 +++--- .../spine/examples/pingh/desktop/Settings.kt | 62 ++++++++++--------- 5 files changed, 113 insertions(+), 101 deletions(-) diff --git a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/IconButton.kt b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/IconButton.kt index b14c5fd2..94fded56 100644 --- a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/IconButton.kt +++ b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/IconButton.kt @@ -35,7 +35,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.FilledIconButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButtonColors -import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.IconButtonDefaults.filledIconButtonColors import androidx.compose.material3.Surface import androidx.compose.material3.TooltipBox import androidx.compose.material3.rememberTooltipState @@ -45,7 +45,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.input.pointer.PointerIcon +import androidx.compose.ui.input.pointer.PointerIcon.Companion.Hand import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Dp @@ -55,14 +55,13 @@ import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.window.PopupPositionProvider -import java.awt.Cursor /** * The proportion of the button's size that the icon occupies. * Since the button is circular, the icon should be scaled down * to avoid truncation at the edges. */ -private const val circularIconSizeMultiplier = 0.75f +private const val circularIconSizeFraction = 0.75f /** * Displays a round button that contains icon. @@ -75,7 +74,7 @@ private const val circularIconSizeMultiplier = 0.75f * @param colors The `IconButtonColors` that is used to resolve the colors used for this icon button * in different states. * @param tooltip The text to be displayed in the tooltip. If `null`, no tooltip is shown. - * @param sizeMultiplier The proportion of the button's size that the icon occupies. + * @param sizeFraction The proportion of the button's size that the icon occupies. */ @Composable @Suppress("LongParameterList" /* For detailed customization. */) @@ -85,9 +84,9 @@ internal fun IconButton( modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = CircleShape, - colors: IconButtonColors = IconButtonDefaults.filledIconButtonColors(), + colors: IconButtonColors = filledIconButtonColors(), tooltip: String? = null, - sizeMultiplier: Float = circularIconSizeMultiplier + sizeFraction: Float = circularIconSizeFraction ) { val wrapper = if (tooltip != null) wrapInTooltipBox(tooltip) else noWrap() wrapper { @@ -95,7 +94,7 @@ internal fun IconButton( onClick = onClick, modifier = modifier .padding(0.dp) - .pointerHoverIcon(PointerIcon(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR))), + .pointerHoverIcon(Hand), enabled = enabled, shape = shape, colors = colors @@ -103,7 +102,7 @@ internal fun IconButton( Icon( painter = icon, contentDescription = null, - modifier = Modifier.fillMaxSize(sizeMultiplier), + modifier = Modifier.fillMaxSize(sizeFraction), tint = colors.contentColor ) } diff --git a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Login.kt b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Login.kt index 82c6b897..1372e752 100644 --- a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Login.kt +++ b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Login.kt @@ -34,6 +34,7 @@ import androidx.compose.foundation.border import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsFocusedAsState import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Arrangement.Center import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -48,9 +49,9 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ButtonDefaults.buttonColors import androidx.compose.material3.Icon -import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.IconButtonDefaults.iconButtonColors import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -60,7 +61,9 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterHorizontally +import androidx.compose.ui.Alignment.Companion.CenterStart +import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.key.Key @@ -74,7 +77,8 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextLinkStyles import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.style.TextDecoration.Companion.None +import androidx.compose.ui.text.style.TextDecoration.Companion.Underline import androidx.compose.ui.text.withLink import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -150,8 +154,8 @@ private fun UsernameEnteringPage( modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.secondary), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + verticalArrangement = Center, + horizontalAlignment = CenterHorizontally ) { ApplicationInfo() Spacer(Modifier.height(35.dp)) @@ -184,12 +188,12 @@ private fun UsernameEnteringPage( private fun ApplicationInfo() { Column( modifier = Modifier.padding(horizontal = 30.dp), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = CenterHorizontally ) { Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically + horizontalArrangement = Center, + verticalAlignment = CenterVertically ) { Icon( painter = painterResource(Res.drawable.pingh), @@ -302,13 +306,13 @@ private fun InputContainer( shape = MaterialTheme.shapes.medium ) .padding(horizontal = 10.dp, vertical = 3.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { Box( modifier = Modifier .weight(1f) .fillMaxWidth(), - contentAlignment = Alignment.CenterStart, + contentAlignment = CenterStart, ) { Placeholder(value.isEmpty()) textField() @@ -397,7 +401,7 @@ private fun LoginButton( .testTag("login-button"), enabled = enabled, shape = MaterialTheme.shapes.medium, - colors = ButtonDefaults.buttonColors( + colors = buttonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary ) @@ -438,8 +442,8 @@ private fun VerificationPage( modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.secondary), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + verticalArrangement = Center, + horizontalAlignment = CenterHorizontally ) { VerificationTitle() Spacer(Modifier.height(25.dp)) @@ -505,8 +509,8 @@ private fun UserCodeField( } .padding(horizontal = 15.dp) .testTag("user-code"), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically + horizontalArrangement = Center, + verticalAlignment = CenterVertically ) { SelectionContainer { Text( @@ -541,7 +545,7 @@ private fun CopyToClipboardIcon( clipboardManager.setText(AnnotatedString(userCode.value)) }, modifier = Modifier.size(30.dp), - colors = IconButtonDefaults.iconButtonColors( + colors = iconButtonColors( contentColor = MaterialTheme.colorScheme.onSecondaryContainer ) ) @@ -575,7 +579,7 @@ private fun VerifyLoginSection( ) { Row( modifier = Modifier.width(280.dp).height(55.dp), - verticalAlignment = Alignment.CenterVertically, + verticalAlignment = CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp) ) { CountdownTimer( @@ -605,10 +609,10 @@ private fun VerificationText(url: Url) { styles = TextLinkStyles( style = SpanStyle( color = MaterialTheme.colorScheme.primary, - textDecoration = TextDecoration.None + textDecoration = None ), hoveredStyle = SpanStyle( - textDecoration = TextDecoration.Underline + textDecoration = Underline ) ) ) @@ -654,10 +658,10 @@ private fun ClickableErrorMessage( styles = TextLinkStyles( style = SpanStyle( color = MaterialTheme.colorScheme.primary, - textDecoration = TextDecoration.None + textDecoration = None ), hoveredStyle = SpanStyle( - textDecoration = TextDecoration.Underline + textDecoration = Underline ) ), linkInteractionListener = { onClick() } @@ -690,8 +694,8 @@ private fun FailedPage(flow: LoginFailed) { modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.secondary), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + verticalArrangement = Center, + horizontalAlignment = CenterHorizontally ) { Text( text = flow.errorMessage.value, @@ -717,7 +721,7 @@ private fun RestartButton(flow: LoginFailed) { .width(240.dp) .height(40.dp), shape = MaterialTheme.shapes.medium, - colors = ButtonDefaults.buttonColors( + colors = buttonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary ) diff --git a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt index dd7aeca9..69a30633 100644 --- a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt +++ b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Mentions.kt @@ -26,7 +26,8 @@ package io.spine.examples.pingh.desktop -import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.Spring.DampingRatioMediumBouncy +import androidx.compose.animation.core.Spring.StiffnessLow import androidx.compose.animation.core.VisibilityThreshold import androidx.compose.animation.core.spring import androidx.compose.foundation.background @@ -51,26 +52,27 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyItemScope import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.CardDefaults.cardColors +import androidx.compose.material3.IconButtonDefaults.iconButtonColors import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.Center +import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.input.pointer.PointerIcon +import androidx.compose.ui.input.pointer.PointerIcon.Companion.Hand import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.testTag -import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.style.TextOverflow.Companion.Ellipsis import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -85,7 +87,6 @@ import io.spine.examples.pingh.client.howMuchTimeHasPassed import io.spine.examples.pingh.client.sorted import io.spine.examples.pingh.mentions.MentionStatus import io.spine.examples.pingh.mentions.MentionView -import java.awt.Cursor import org.jetbrains.compose.resources.painterResource /** @@ -119,13 +120,13 @@ internal fun MentionsPage( * * @param flow The flow for managing the lifecycle of mentions. * @param toSettingsPage The navigation to the 'Settings' page. - * @param appIconMultiplier The proportion of the button's size that the app icon occupies. + * @param appIconFraction The proportion of the button's size that the app icon occupies. */ @Composable private fun ToolBar( flow: MentionsFlow, toSettingsPage: () -> Unit, - appIconMultiplier: Float = 0.8f + appIconFraction: Float = 0.8f ) { val contentColor = MaterialTheme.colorScheme.onSecondary val borderColor = MaterialTheme.colorScheme.onBackground @@ -143,16 +144,16 @@ private fun ToolBar( ) } .padding(start = 20.dp, end = 13.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { IconButton( icon = painterResource(Res.drawable.pingh), onClick = toSettingsPage, modifier = Modifier.size(50.dp).testTag("settings-button"), - colors = IconButtonDefaults.iconButtonColors( + colors = iconButtonColors( contentColor = contentColor ), - sizeMultiplier = appIconMultiplier + sizeFraction = appIconFraction ) Spacer(Modifier.width(5.dp)) Text( @@ -168,7 +169,7 @@ private fun ToolBar( flow.updateMentions() }, modifier = Modifier.size(44.dp), - colors = IconButtonDefaults.iconButtonColors( + colors = iconButtonColors( contentColor = contentColor ) ) @@ -241,13 +242,13 @@ private fun LazyItemScope.MentionCard( .hoverable(interactionSource) .animateItem( placementSpec = spring( - dampingRatio = Spring.DampingRatioMediumBouncy, - stiffness = Spring.StiffnessLow, + dampingRatio = DampingRatioMediumBouncy, + stiffness = StiffnessLow, visibilityThreshold = IntOffset.VisibilityThreshold ) ), shape = shape, - colors = CardDefaults.elevatedCardColors( + colors = cardColors( containerColor = containerColor, contentColor = MaterialTheme.colorScheme.onSecondary ) @@ -255,7 +256,7 @@ private fun LazyItemScope.MentionCard( Row( modifier = Modifier.padding(start = 15.dp, end = 10.dp), horizontalArrangement = Arrangement.spacedBy(10.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { Avatar( url = mention.whoMentioned.avatarUrl, @@ -264,7 +265,7 @@ private fun LazyItemScope.MentionCard( MentionCardText(flow, mention, isHovered) Row( modifier = Modifier.fillMaxHeight(), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { SnoozeButton(flow, mention, isHovered) PinButton(flow, mention, isHovered) @@ -292,12 +293,12 @@ private fun RowScope.MentionCardText( } Column( modifier = Modifier.fillMaxHeight().weight(1f), - verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically) + verticalArrangement = Arrangement.spacedBy(4.dp, CenterVertically) ) { MentionTitle(flow, mention, isParentHovered) Text( text = "$time, by ${mention.whoMentioned.username.value}", - overflow = TextOverflow.Ellipsis, + overflow = Ellipsis, maxLines = 1, style = MaterialTheme.typography.bodySmall ) @@ -352,7 +353,7 @@ private fun MentionTitle( this } } - .pointerHoverIcon(PointerIcon(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR))) + .pointerHoverIcon(Hand) .hoverable(interactionSource) .clickable( interactionSource = interactionSource, @@ -361,7 +362,7 @@ private fun MentionTitle( ) .testTag("mention-title"), color = color, - overflow = TextOverflow.Ellipsis, + overflow = Ellipsis, maxLines = 1, style = MaterialTheme.typography.bodyLarge ) @@ -394,8 +395,7 @@ private fun SnoozeButton( mention.status == MentionStatus.SNOOZED -> Text( text = "Snoozed", - modifier = Modifier.size(50.dp) - .wrapContentSize(Alignment.Center), + modifier = Modifier.size(50.dp).wrapContentSize(Center), style = MaterialTheme.typography.bodySmall ) } @@ -409,14 +409,14 @@ private fun SnoozeButton( * @param flow The flow for managing the lifecycle of mentions. * @param mention The mention whose information is displayed. * @param isParentHovered Whether the parent mention card is being hovered. - * @param sizeMultiplier The proportion of the button's size that the icon occupies. + * @param sizeFraction The proportion of the button's size that the icon occupies. */ @Composable private fun PinButton( flow: MentionsFlow, mention: MentionView, isParentHovered: Boolean, - sizeMultiplier: Float = 0.6f + sizeFraction: Float = 0.6f ) { val (iconRes, onClick) = when { isParentHovered && !mention.pinned -> Res.drawable.pin to { flow.pin(mention.id) } @@ -428,7 +428,7 @@ private fun PinButton( icon = painterResource(iconRes), onClick = onClick, modifier = Modifier.testTag("pin-button"), - sizeMultiplier = sizeMultiplier + sizeFraction = sizeFraction ) } } @@ -439,14 +439,14 @@ private fun PinButton( * @param icon The painter to draw icon. * @param onClick Called when this icon button is clicked. * @param modifier The modifier to be applied to this icon button. - * @param sizeMultiplier The proportion of the button's size that the icon occupies. + * @param sizeFraction The proportion of the button's size that the icon occupies. */ @Composable private fun MentionIconButton( icon: Painter, onClick: () -> Unit, modifier: Modifier = Modifier, - sizeMultiplier: Float = 0.85f + sizeFraction: Float = 0.85f ) { val interactionSource = remember { MutableInteractionSource() } val isHovered by interactionSource.collectIsHoveredAsState() @@ -463,9 +463,9 @@ private fun MentionIconButton( .hoverable(interactionSource) .then(modifier), shape = CircleShape, - colors = IconButtonDefaults.iconButtonColors( + colors = iconButtonColors( contentColor = color ), - sizeMultiplier = sizeMultiplier + sizeFraction = sizeFraction ) } diff --git a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Navigation.kt b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Navigation.kt index 3a7ce7ab..920d886f 100644 --- a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Navigation.kt +++ b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Navigation.kt @@ -30,6 +30,9 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import io.spine.examples.pingh.client.PinghApplication +import io.spine.examples.pingh.desktop.Page.LOGIN +import io.spine.examples.pingh.desktop.Page.MENTIONS +import io.spine.examples.pingh.desktop.Page.SETTINGS /** * Displays the current page of the application. @@ -40,31 +43,31 @@ import io.spine.examples.pingh.client.PinghApplication internal fun CurrentPage(application: PinghApplication) { val currentPage = remember { mutableStateOf( - if (application.isLoggedIn()) Page.MENTIONS else Page.LOGIN + if (application.isLoggedIn()) MENTIONS else LOGIN ) } when (currentPage.value) { - Page.LOGIN -> LoginPage( + LOGIN -> LoginPage( flow = application.startLoginFlow(), toMentionsPage = { - currentPage.value = Page.MENTIONS + currentPage.value = MENTIONS } ) - Page.MENTIONS -> MentionsPage( + MENTIONS -> MentionsPage( flow = application.startMentionsFlow(), toSettingsPage = { - currentPage.value = Page.SETTINGS + currentPage.value = SETTINGS } ) - Page.SETTINGS -> SettingsPage( + SETTINGS -> SettingsPage( flow = application.startSettingsFlow(), toMentionsPage = { - currentPage.value = Page.MENTIONS + currentPage.value = MENTIONS }, toLoginPage = { - currentPage.value = Page.LOGIN + currentPage.value = LOGIN } ) } diff --git a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Settings.kt b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Settings.kt index dbc44255..cafeeceb 100644 --- a/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Settings.kt +++ b/desktop/src/main/kotlin/io/spine/examples/pingh/desktop/Settings.kt @@ -35,6 +35,7 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsFocusedAsState import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Arrangement.Center import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope @@ -53,10 +54,11 @@ import androidx.compose.foundation.selection.selectableGroup import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.verticalScroll import androidx.compose.material.Divider -import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ButtonDefaults.outlinedButtonColors import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.CardDefaults.cardColors +import androidx.compose.material3.IconButtonDefaults.filledIconButtonColors +import androidx.compose.material3.IconButtonDefaults.iconButtonColors import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton @@ -73,6 +75,10 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterHorizontally +import androidx.compose.ui.Alignment.Companion.CenterStart +import androidx.compose.ui.Alignment.Companion.CenterVertically +import androidx.compose.ui.Alignment.Companion.End import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.scale @@ -82,12 +88,12 @@ import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.key import androidx.compose.ui.input.key.onKeyEvent import androidx.compose.ui.platform.testTag -import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.Role.Companion.RadioButton import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.style.TextOverflow.Companion.Ellipsis import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -159,13 +165,13 @@ private fun SettingsHeader( .fillMaxWidth() .height(60.dp) .padding(horizontal = 10.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { IconButton( icon = painterResource(Res.drawable.back), onClick = onExit, modifier = Modifier.size(35.dp), - colors = IconButtonDefaults.iconButtonColors( + colors = iconButtonColors( contentColor = MaterialTheme.colorScheme.onSecondary ) ) @@ -196,7 +202,7 @@ private fun SettingsBox( ) { Card( modifier = Modifier.fillMaxSize(), - colors = CardDefaults.cardColors( + colors = cardColors( containerColor = MaterialTheme.colorScheme.secondary, contentColor = MaterialTheme.colorScheme.onSecondary ) @@ -229,7 +235,7 @@ private fun Profile( .fillMaxWidth() .height(60.dp) .padding(vertical = 4.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { Avatar( name = username, @@ -257,11 +263,11 @@ private fun ProfileControl( modifier = Modifier .fillMaxSize() .padding(top = 4.dp), - verticalArrangement = Arrangement.Center + verticalArrangement = Center ) { Text( text = username.value, - overflow = TextOverflow.Ellipsis, + overflow = Ellipsis, maxLines = 1, style = MaterialTheme.typography.bodyLarge ) @@ -315,12 +321,12 @@ private fun SettingsButton( usePrimaryColors: Boolean = false ) { val colors = if (usePrimaryColors) { - ButtonDefaults.outlinedButtonColors( + outlinedButtonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary ) } else { - ButtonDefaults.outlinedButtonColors( + outlinedButtonColors( containerColor = MaterialTheme.colorScheme.secondary, contentColor = MaterialTheme.colorScheme.onSecondary ) @@ -421,7 +427,7 @@ private fun Option( ) { Row( modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { Text( text = title, @@ -452,7 +458,7 @@ private fun SnoozeTimeSegmentedButtonRow(state: SettingsState) { Row( modifier = Modifier.selectableGroup(), horizontalArrangement = Arrangement.spacedBy((-1).dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { snoozeTimeOptions.forEachIndexed { index, snoozeTime -> SegmentedButton( @@ -504,7 +510,7 @@ private fun SegmentedButton( modifier = Modifier .width(70.dp) .height(20.dp) - .semantics { role = Role.RadioButton } + .semantics { role = RadioButton } .background(containerColor, shape) .border(border, shape) .clip(shape) @@ -653,7 +659,7 @@ private fun IgnoredSourcesControl( * @param onClick Called when this icon button is clicked. * @param tooltip The text to be displayed in the tooltip. * @param enabled Controls the enabled state of this icon button. - * @param sizeMultiplier The proportion of the button's size that the icon occupies. + * @param sizeFraction The proportion of the button's size that the icon occupies. */ @Composable private fun SettingsIconButton( @@ -661,7 +667,7 @@ private fun SettingsIconButton( onClick: () -> Unit, tooltip: String, enabled: Boolean = true, - sizeMultiplier: Float = 0.85f + sizeFraction: Float = 0.85f ) { val contentColor = if (enabled) { MaterialTheme.colorScheme.onSecondary @@ -674,13 +680,13 @@ private fun SettingsIconButton( modifier = Modifier.size(26.dp), enabled = enabled, shape = MaterialTheme.shapes.small, - colors = IconButtonDefaults.filledIconButtonColors( + colors = filledIconButtonColors( containerColor = MaterialTheme.colorScheme.secondary, contentColor = contentColor, disabledContainerColor = MaterialTheme.colorScheme.secondary ), tooltip = tooltip, - sizeMultiplier = sizeMultiplier + sizeFraction = sizeFraction ) } @@ -733,10 +739,10 @@ private fun IgnoredSourceItem( modifier = Modifier.fillMaxWidth() .height(30.dp) .background(containerColor) - .semantics { role = Role.RadioButton } + .semantics { role = RadioButton } .clickable { selected.value = if (!isSelected) source else null } .padding(start = 5.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { Text( text = annotationString, @@ -770,8 +776,8 @@ private fun AddIgnoredSourceDialog(state: SettingsState, onExit: () -> Unit) { shape = MaterialTheme.shapes.medium ) .padding(horizontal = 30.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(15.dp, Alignment.CenterVertically) + horizontalAlignment = CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(15.dp, CenterVertically) ) { OutlinedTextField( value = org, @@ -909,13 +915,13 @@ private fun OutlinedTextFieldContainer( shape = MaterialTheme.shapes.extraSmall ) .padding(horizontal = 10.dp, vertical = 3.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = CenterVertically ) { Box( modifier = Modifier .weight(1f) .fillMaxWidth(), - contentAlignment = Alignment.CenterStart, + contentAlignment = CenterStart, ) { textField() } @@ -936,7 +942,7 @@ private fun AllReposSwitch( ) { Row( modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, + verticalAlignment = CenterVertically, horizontalArrangement = Arrangement.spacedBy(5.dp) ) { Switch( @@ -1004,7 +1010,7 @@ private fun DialogControl( isAddTriggered.value = false Row( modifier = Modifier.fillMaxWidth().height(30.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End) + horizontalArrangement = Arrangement.spacedBy(10.dp, End) ) { SettingsButton( onClick = onCancel,