Skip to content

Commit 26de422

Browse files
committed
android: little more liquid glass
1 parent 8760757 commit 26de422

3 files changed

Lines changed: 95 additions & 128 deletions

File tree

android/app/src/main/java/me/kavishdevar/librepods/composables/ConfirmationDialog.kt

Lines changed: 67 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,39 @@
11
package me.kavishdevar.librepods.composables
22

33
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.clickable
45
import androidx.compose.foundation.isSystemInDarkTheme
56
import androidx.compose.foundation.layout.Arrangement
67
import androidx.compose.foundation.layout.Box
78
import androidx.compose.foundation.layout.Column
89
import androidx.compose.foundation.layout.Row
9-
import androidx.compose.foundation.layout.fillMaxHeight
10+
import androidx.compose.foundation.layout.Spacer
11+
import androidx.compose.foundation.layout.fillMaxSize
1012
import androidx.compose.foundation.layout.fillMaxWidth
1113
import androidx.compose.foundation.layout.height
1214
import androidx.compose.foundation.layout.padding
1315
import androidx.compose.foundation.layout.requiredWidthIn
14-
import androidx.compose.foundation.layout.width
1516
import androidx.compose.foundation.shape.RoundedCornerShape
16-
import androidx.compose.material3.HorizontalDivider
1717
import androidx.compose.material3.Text
1818
import androidx.compose.runtime.Composable
1919
import androidx.compose.runtime.MutableState
20-
import androidx.compose.runtime.getValue
21-
import androidx.compose.runtime.mutableStateOf
22-
import androidx.compose.runtime.remember
23-
import androidx.compose.runtime.setValue
2420
import androidx.compose.ui.Alignment
2521
import androidx.compose.ui.Modifier
2622
import androidx.compose.ui.draw.clip
2723
import androidx.compose.ui.graphics.Color
28-
import androidx.compose.ui.input.pointer.PointerEventType
29-
import androidx.compose.ui.input.pointer.pointerInput
3024
import androidx.compose.ui.text.TextStyle
3125
import androidx.compose.ui.text.font.Font
3226
import androidx.compose.ui.text.font.FontFamily
3327
import androidx.compose.ui.text.font.FontWeight
34-
import androidx.compose.ui.text.style.TextAlign
3528
import androidx.compose.ui.unit.dp
3629
import androidx.compose.ui.unit.sp
37-
import androidx.compose.ui.window.Dialog
38-
import dev.chrisbanes.haze.HazeState
39-
import dev.chrisbanes.haze.hazeEffect
40-
import dev.chrisbanes.haze.materials.CupertinoMaterials
41-
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
30+
import com.kyant.backdrop.Backdrop
31+
import com.kyant.backdrop.drawBackdrop
32+
import com.kyant.backdrop.effects.blur
33+
import com.kyant.backdrop.effects.colorFilter
34+
import com.kyant.backdrop.effects.refraction
4235
import me.kavishdevar.librepods.R
4336

44-
@ExperimentalHazeMaterialsApi
4537
@Composable
4638
fun ConfirmationDialog(
4739
showDialog: MutableState<Boolean>,
@@ -51,133 +43,100 @@ fun ConfirmationDialog(
5143
dismissText: String = "Cancel",
5244
onConfirm: () -> Unit,
5345
onDismiss: () -> Unit = { showDialog.value = false },
54-
hazeState: HazeState,
46+
backdrop: Backdrop,
5547
) {
56-
val isDarkTheme = isSystemInDarkTheme()
57-
val textColor = if (isDarkTheme) Color.White else Color.Black
58-
val accentColor = if (isDarkTheme) Color(0xFF007AFF) else Color(0xFF3C6DF5)
5948
if (showDialog.value) {
60-
Dialog(onDismissRequest = { showDialog.value = false }) {
49+
val isLightTheme = !isSystemInDarkTheme()
50+
val contentColor = if (isLightTheme) Color.Black else Color.White
51+
val accentColor = if (isLightTheme) Color(0xFF0088FF) else Color(0xFF0091FF)
52+
val containerColor = if (isLightTheme) Color(0xFFFAFAFA).copy(0.6f) else Color(0xFF121212).copy(0.4f)
53+
val dimColor = if (isLightTheme) Color(0xFF29293A).copy(0.23f) else Color(0xFF121212).copy(0.56f)
54+
55+
Box(
56+
Modifier
57+
.background(dimColor)
58+
.fillMaxSize()
59+
.clickable(onClick = onDismiss)
60+
) {
6161
Box(
62-
modifier = Modifier
62+
Modifier
63+
.align(Alignment.Center)
64+
.drawBackdrop(
65+
backdrop,
66+
{ RoundedCornerShape(48f.dp) },
67+
// highlight = { Highlight { HighlightStyle.Solid } },
68+
onDrawSurface = { drawRect(containerColor) }
69+
) {
70+
colorFilter(
71+
brightness = if (isLightTheme) 0.2f else 0.1f,
72+
saturation = 1.5f
73+
)
74+
blur(if (isLightTheme) 16f.dp.toPx() else 8f.dp.toPx())
75+
refraction(24f.dp.toPx(), 48f.dp.toPx(), true)
76+
}
6377
.fillMaxWidth(0.75f)
6478
.requiredWidthIn(min = 200.dp, max = 360.dp)
65-
.background(Color.Transparent, RoundedCornerShape(14.dp))
66-
.clip(RoundedCornerShape(14.dp))
67-
.hazeEffect(
68-
hazeState,
69-
style = CupertinoMaterials.regular(
70-
containerColor = if (isDarkTheme) Color(0xFF1C1C1E).copy(alpha = 0.95f) else Color.White.copy(alpha = 0.95f)
71-
)
72-
)
7379
) {
74-
Column(horizontalAlignment = Alignment.CenterHorizontally) {
75-
androidx.compose.foundation.layout.Spacer(modifier = Modifier.height(24.dp))
80+
Column(horizontalAlignment = Alignment.Start) {
81+
Spacer(modifier = Modifier.height(28.dp))
7682
Text(
7783
title,
7884
style = TextStyle(
7985
fontSize = 16.sp,
8086
fontWeight = FontWeight.Bold,
81-
color = textColor,
87+
color = contentColor,
8288
fontFamily = FontFamily(Font(R.font.sf_pro))
8389
),
84-
textAlign = TextAlign.Center,
8590
modifier = Modifier.padding(horizontal = 16.dp)
8691
)
87-
androidx.compose.foundation.layout.Spacer(modifier = Modifier.height(12.dp))
92+
Spacer(modifier = Modifier.height(16.dp))
8893
Text(
8994
message,
9095
style = TextStyle(
9196
fontSize = 14.sp,
92-
color = textColor.copy(alpha = 0.8f),
97+
color = contentColor.copy(alpha = 0.8f),
9398
fontFamily = FontFamily(Font(R.font.sf_pro))
9499
),
95-
textAlign = TextAlign.Center,
96100
modifier = Modifier.padding(horizontal = 16.dp)
97101
)
98-
androidx.compose.foundation.layout.Spacer(modifier = Modifier.height(16.dp))
99-
HorizontalDivider(
100-
thickness = 1.dp,
101-
color = Color(0x40888888),
102-
modifier = Modifier.fillMaxWidth()
103-
)
104-
var leftPressed by remember { mutableStateOf(false) }
105-
var rightPressed by remember { mutableStateOf(false) }
106-
val pressedColor = if (isDarkTheme) Color(0x40888888) else Color(0x40D9D9D9)
102+
Spacer(modifier = Modifier.height(16.dp))
103+
107104
Row(
108-
modifier = Modifier
109-
.fillMaxWidth()
110-
.height(48.dp)
111-
.pointerInput(Unit) {
112-
awaitPointerEventScope {
113-
while (true) {
114-
val event = awaitPointerEvent()
115-
val position = event.changes.first().position
116-
val width = size.width.toFloat()
117-
val height = size.height.toFloat()
118-
val isWithinBounds = position.y >= 0 && position.y <= height
119-
val isLeft = position.x < width / 2
120-
event.changes.first().consume()
121-
when (event.type) {
122-
PointerEventType.Press -> {
123-
if (isWithinBounds) {
124-
leftPressed = isLeft
125-
rightPressed = !isLeft
126-
} else {
127-
leftPressed = false
128-
rightPressed = false
129-
}
130-
}
131-
PointerEventType.Move -> {
132-
if (isWithinBounds) {
133-
leftPressed = isLeft
134-
rightPressed = !isLeft
135-
} else {
136-
leftPressed = false
137-
rightPressed = false
138-
}
139-
}
140-
PointerEventType.Release -> {
141-
if (isWithinBounds) {
142-
if (leftPressed) {
143-
onDismiss()
144-
} else if (rightPressed) {
145-
onConfirm()
146-
}
147-
}
148-
leftPressed = false
149-
rightPressed = false
150-
}
151-
}
152-
}
153-
}
154-
},
155-
horizontalArrangement = Arrangement.Start,
105+
Modifier
106+
.padding(24.dp, 12.dp, 24.dp, 24.dp)
107+
.fillMaxWidth(),
108+
horizontalArrangement = Arrangement.spacedBy(16.dp),
156109
verticalAlignment = Alignment.CenterVertically
157110
) {
158111
Box(
159-
modifier = Modifier
112+
Modifier
113+
.clip(RoundedCornerShape(50.dp))
114+
.background(containerColor.copy(0.2f))
115+
.clickable(onClick = onDismiss)
116+
.height(48.dp)
160117
.weight(1f)
161-
.fillMaxHeight()
162-
.background(if (leftPressed) pressedColor else Color.Transparent),
118+
.padding(horizontal = 16.dp),
163119
contentAlignment = Alignment.Center
164120
) {
165-
Text(dismissText, color = accentColor)
121+
Text(
122+
dismissText,
123+
style = TextStyle(contentColor, 16.sp)
124+
)
166125
}
167126
Box(
168-
modifier = Modifier
169-
.width(1.dp)
170-
.fillMaxHeight()
171-
.background(Color(0x40888888))
172-
)
173-
Box(
174-
modifier = Modifier
127+
Modifier
128+
.clip(RoundedCornerShape(50.dp))
129+
.background(accentColor)
130+
.clickable(onClick = onConfirm)
131+
.height(48.dp)
175132
.weight(1f)
176-
.fillMaxHeight()
177-
.background(if (rightPressed) pressedColor else Color.Transparent),
133+
.padding(horizontal = 16.dp),
178134
contentAlignment = Alignment.Center
179135
) {
180-
Text(confirmText, color = accentColor)
136+
Text(
137+
confirmText,
138+
style = TextStyle(Color.White, 16.sp)
139+
)
181140
}
182141
}
183142
}

android/app/src/main/java/me/kavishdevar/librepods/composables/StyledSlider.kt

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -133,16 +133,18 @@ fun StyledSlider(
133133
val density = LocalDensity.current
134134

135135
val content = @Composable {
136-
Box(Modifier.fillMaxWidth()) {
136+
Box(
137+
Modifier.fillMaxWidth(if (startIcon == null && endIcon == null) 0.95f else 1f)
138+
) {
137139
Box(Modifier
138140
.backdrop(sliderBackdrop)
139141
.fillMaxWidth()) {
140142
Column(
141143
modifier = Modifier
142144
.fillMaxWidth(1f)
143-
.padding(vertical = 8.dp),
145+
.padding(vertical = 12.dp),
144146
horizontalAlignment = Alignment.CenterHorizontally,
145-
verticalArrangement = Arrangement.spacedBy(8.dp)
147+
verticalArrangement = Arrangement.spacedBy(12.dp)
146148
) {
147149
if (label != null) {
148150
Text(
@@ -152,13 +154,14 @@ fun StyledSlider(
152154
fontWeight = FontWeight.Medium,
153155
color = labelTextColor,
154156
fontFamily = FontFamily(Font(R.font.sf_pro))
155-
)
157+
),
156158
)
157159
}
158160

159161
if (startLabel != null || endLabel != null) {
160162
Row(
161-
modifier = Modifier.fillMaxWidth(),
163+
modifier = Modifier
164+
.fillMaxWidth(),
162165
horizontalArrangement = Arrangement.SpaceBetween
163166
) {
164167
Text(
@@ -183,15 +186,18 @@ fun StyledSlider(
183186
}
184187

185188
Row(
186-
modifier = Modifier.fillMaxWidth(),
189+
modifier = Modifier
190+
.fillMaxWidth()
191+
.padding(vertical = 4.dp)
192+
.then(if (startIcon == null && endIcon == null) Modifier.padding(horizontal = 12.dp) else Modifier),
187193
verticalAlignment = Alignment.CenterVertically,
188194
horizontalArrangement = Arrangement.spacedBy(0.dp)
189195
) {
190196
if (startIcon != null) {
191197
Text(
192198
text = startIcon,
193199
style = TextStyle(
194-
fontSize = 16.sp,
200+
fontSize = 18.sp,
195201
fontWeight = FontWeight.Normal,
196202
color = labelTextColor,
197203
fontFamily = FontFamily(Font(R.font.sf_pro))
@@ -240,7 +246,7 @@ fun StyledSlider(
240246
Text(
241247
text = endIcon,
242248
style = TextStyle(
243-
fontSize = 16.sp,
249+
fontSize = 18.sp,
244250
fontWeight = FontWeight.Normal,
245251
color = labelTextColor,
246252
fontFamily = FontFamily(Font(R.font.sf_pro))
@@ -260,10 +266,10 @@ fun StyledSlider(
260266
Modifier
261267
.graphicsLayer {
262268
val startOffset =
263-
if (startIcon != null) startIconWidthState.floatValue + with(density) { 24.dp.toPx() } else 0f
269+
if (startIcon != null) startIconWidthState.floatValue + with(density) { 24.dp.toPx() } else with(density) { 8.dp.toPx() }
264270
translationX =
265271
startOffset + fraction * trackWidthState.floatValue - size.width / 2f
266-
translationY = trackPositionState.floatValue / 2f
272+
translationY = if (startLabel != null || endLabel != null) trackPositionState.floatValue + with(density) { 22.dp.toPx() } + size.height / 2f else trackPositionState.floatValue + with(density) { 4.dp.toPx() }
267273
}
268274
.draggable(
269275
rememberDraggableState { delta ->
@@ -372,13 +378,13 @@ private fun snapIfClose(value: Float, points: List<Float>, threshold: Float = 0.
372378
return if (kotlin.math.abs(nearest - value) <= threshold) nearest else value
373379
}
374380

375-
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
381+
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
376382
@Composable
377383
fun StyledSliderPreview() {
378384
val a = remember { mutableFloatStateOf(1f) }
379385
Box(
380386
Modifier
381-
.background(if (isSystemInDarkTheme()) Color(0xFF121212) else Color(0xFFF0F0F0))
387+
.background(if (isSystemInDarkTheme()) Color(0xFF000000) else Color(0xFFF0F0F0))
382388
.padding(16.dp)
383389
.fillMaxSize()
384390
) {
@@ -393,8 +399,8 @@ fun StyledSliderPreview() {
393399
},
394400
valueRange = 0f..2f,
395401
independent = true,
396-
startIcon = "A",
397-
endIcon = "B"
402+
startLabel = "A",
403+
endLabel = "B"
398404
)
399405
}
400406
}

0 commit comments

Comments
 (0)