@@ -43,7 +43,7 @@ import androidx.compose.foundation.layout.isImeVisible
4343import androidx.compose.foundation.layout.padding
4444import androidx.compose.foundation.layout.wrapContentHeight
4545import androidx.compose.foundation.layout.wrapContentSize
46- import androidx.compose.foundation.shape.RoundedCornerShape
46+ import androidx.compose.foundation.shape.GenericShape
4747import androidx.compose.material3.Surface
4848import androidx.compose.runtime.Composable
4949import androidx.compose.runtime.LaunchedEffect
@@ -55,12 +55,20 @@ import androidx.compose.ui.Alignment
5555import androidx.compose.ui.Modifier
5656import androidx.compose.ui.draw.clip
5757import androidx.compose.ui.draw.drawBehind
58+ import androidx.compose.ui.geometry.CornerRadius
5859import androidx.compose.ui.geometry.Offset
60+ import androidx.compose.ui.geometry.Rect
61+ import androidx.compose.ui.geometry.RoundRect
5962import androidx.compose.ui.geometry.Size
63+ import androidx.compose.ui.geometry.toRect
6064import androidx.compose.ui.graphics.Color
61- import androidx.compose.ui.graphics.RectangleShape
65+ import androidx.compose.ui.graphics.Path
66+ import androidx.compose.ui.graphics.drawscope.Fill
67+ import androidx.compose.ui.graphics.drawscope.Stroke
6268import androidx.compose.ui.platform.LocalContext
6369import androidx.compose.ui.platform.LocalDensity
70+ import androidx.compose.ui.unit.Density
71+ import androidx.compose.ui.unit.Dp
6472import androidx.compose.ui.unit.IntOffset
6573import androidx.compose.ui.unit.dp
6674import androidx.compose.ui.window.Popup
@@ -340,11 +348,12 @@ fun EnabledMessageComposer(
340348 showAttachments(false )
341349 }
342350 ) {
343- val rippleColor = colorsScheme().surface
344- val shape = if (isImeVisible) {
345- RectangleShape
346- } else {
347- RoundedCornerShape (dimensions().corner14x)
351+ val rippleColor = colorsScheme().surfaceContainerLowest
352+ val borderColor = colorsScheme().divider
353+ val borderWidthPx = if (isImeVisible) 0f else dimensions().spacing1x.toPx(density)
354+ val cornerRadiusPx = if (isImeVisible) 0f else dimensions().corner14x.toPx(density)
355+ val shape = GenericShape { size, _ ->
356+ addPath(calculateOptionsPath(cornerRadiusPx, rippleProgress.value, isImeVisible, size))
348357 }
349358
350359 Box (
@@ -365,21 +374,22 @@ fun EnabledMessageComposer(
365374 .clip(shape)
366375 .drawBehind {
367376 if (! hideRipple || rippleProgress.value > 0f ) {
368- val maxRadius = size.getDistanceToCorner(Offset (0f , 0f ))
369- val currentRadius = maxRadius * rippleProgress.value
370-
371- drawCircle(
372- color = rippleColor,
373- radius = currentRadius,
374- center = Offset (
375- 0f ,
376- if (isImeVisible) {
377- 0f
378- } else {
379- size.height
380- }
377+ calculateOptionsPath(cornerRadiusPx, rippleProgress.value, isImeVisible, size).let {
378+ drawPath(
379+ path = it,
380+ color = rippleColor,
381+ style = Fill
381382 )
382- )
383+ if (borderWidthPx > 0f ) {
384+ drawPath(
385+ path = it,
386+ color = borderColor,
387+ style = Stroke (
388+ width = borderWidthPx * 2f // double to make inner stroke, outer half is clipped anyway
389+ )
390+ )
391+ }
392+ }
383393 }
384394 }
385395
@@ -416,7 +426,30 @@ fun EnabledMessageComposer(
416426 }
417427}
418428
419- fun Size.getDistanceToCorner (corner : Offset ): Float {
429+ private fun Size.getDistanceToCorner (corner : Offset ): Float {
420430 val cornerOffset = Offset (width - corner.x, height - corner.y)
421431 return cornerOffset.getDistance()
422432}
433+
434+ private fun calculateOptionsPath (cornerRadiusPx : Float , rippleProgress : Float , isImeVisible : Boolean , size : Size ): Path {
435+ val ripplePath = Path ()
436+ ripplePath.addOval(
437+ oval = Rect (
438+ center = Offset (
439+ x = 0f ,
440+ y = if (isImeVisible) 0f else size.height
441+ ),
442+ radius = rippleProgress * size.getDistanceToCorner(Offset (0f , 0f ))
443+ )
444+ )
445+ val shapePath = Path ()
446+ shapePath.addRoundRect(
447+ roundRect = RoundRect (
448+ rect = size.toRect(),
449+ cornerRadius = CornerRadius (cornerRadiusPx, cornerRadiusPx)
450+ )
451+ )
452+ return ripplePath.and (shapePath)
453+ }
454+
455+ private fun Dp.toPx (density : Density ) = with (density) { toPx() }
0 commit comments