Skip to content

Commit 7e5ee67

Browse files
committed
android: small ui tweaks
1 parent 5f08edd commit 7e5ee67

File tree

10 files changed

+693
-598
lines changed

10 files changed

+693
-598
lines changed

android/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
crowdin.yml
12
*.iml
23
.gradle
34
/local.properties

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

Lines changed: 9 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -20,42 +20,32 @@
2020

2121
package me.kavishdevar.librepods.composables
2222

23-
import androidx.compose.foundation.background
2423
import androidx.compose.foundation.isSystemInDarkTheme
2524
import androidx.compose.foundation.layout.Arrangement
2625
import androidx.compose.foundation.layout.Box
2726
import androidx.compose.foundation.layout.Column
28-
import androidx.compose.foundation.layout.Row
2927
import androidx.compose.foundation.layout.fillMaxWidth
30-
import androidx.compose.foundation.layout.height
3128
import androidx.compose.foundation.layout.padding
32-
import androidx.compose.foundation.layout.size
33-
import androidx.compose.foundation.shape.CircleShape
34-
import androidx.compose.foundation.shape.RoundedCornerShape
35-
import androidx.compose.material3.ExperimentalMaterial3Api
36-
import androidx.compose.material3.Slider
37-
import androidx.compose.material3.SliderDefaults
38-
import androidx.compose.material3.Text
3929
import androidx.compose.runtime.Composable
4030
import androidx.compose.runtime.LaunchedEffect
4131
import androidx.compose.runtime.DisposableEffect
4232
import androidx.compose.runtime.mutableFloatStateOf
4333
import androidx.compose.runtime.remember
4434
import androidx.compose.ui.Alignment
4535
import androidx.compose.ui.Modifier
46-
import androidx.compose.ui.draw.shadow
4736
import androidx.compose.ui.graphics.Color
37+
import androidx.compose.ui.res.stringResource
4838
import androidx.compose.ui.text.TextStyle
4939
import androidx.compose.ui.text.font.FontWeight
5040
import androidx.compose.ui.tooling.preview.Preview
5141
import androidx.compose.ui.unit.dp
5242
import androidx.compose.ui.unit.sp
43+
import me.kavishdevar.librepods.R
5344
import me.kavishdevar.librepods.services.ServiceManager
5445
import me.kavishdevar.librepods.utils.AACPManager
5546
import kotlin.io.encoding.ExperimentalEncodingApi
5647
import kotlin.math.roundToInt
5748

58-
@OptIn(ExperimentalMaterial3Api::class)
5949
@Composable
6050
fun AdaptiveStrengthSlider() {
6151
val sliderValue = remember { mutableFloatStateOf(0f) }
@@ -100,80 +90,20 @@ fun AdaptiveStrengthSlider() {
10090

10191
Column(
10292
modifier = Modifier
103-
.fillMaxWidth()
104-
.padding(horizontal = 8.dp),
93+
.fillMaxWidth(),
10594
horizontalAlignment = Alignment.CenterHorizontally
10695
) {
107-
Slider(
108-
value = sliderValue.floatValue,
96+
StyledSlider(
97+
mutableFloatState = sliderValue,
10998
onValueChange = {
11099
sliderValue.floatValue = snapIfClose(it, listOf(0f, 50f, 100f))
111100
},
112101
valueRange = 0f..100f,
113-
onValueChangeFinished = {
114-
sliderValue.floatValue = snapIfClose(sliderValue.floatValue.roundToInt().toFloat(), listOf(0f, 50f, 100f))
115-
service.aacpManager.sendControlCommand(
116-
identifier = AACPManager.Companion.ControlCommandIdentifiers.AUTO_ANC_STRENGTH.value,
117-
value = (100 - sliderValue.floatValue).toInt()
118-
)
119-
},
120-
modifier = Modifier
121-
.fillMaxWidth()
122-
.height(36.dp),
123-
colors = SliderDefaults.colors(
124-
thumbColor = thumbColor,
125-
inactiveTrackColor = trackColor
126-
),
127-
thumb = {
128-
Box(
129-
modifier = Modifier
130-
.size(24.dp)
131-
.shadow(4.dp, CircleShape)
132-
.background(thumbColor, CircleShape)
133-
)
134-
},
135-
track = {
136-
Box(
137-
modifier = Modifier
138-
.fillMaxWidth()
139-
.height(12.dp),
140-
contentAlignment = Alignment.CenterStart
141-
)
142-
{
143-
Box(
144-
modifier = Modifier
145-
.fillMaxWidth()
146-
.height(4.dp)
147-
.background(trackColor, RoundedCornerShape(4.dp))
148-
)
149-
}
150-
151-
}
102+
snapPoints = listOf(0f, 50f, 100f),
103+
startLabel = stringResource(R.string.less_noise),
104+
endLabel = stringResource(R.string.more_noise),
105+
independent = false
152106
)
153-
154-
Row(
155-
modifier = Modifier.fillMaxWidth(),
156-
horizontalArrangement = Arrangement.SpaceBetween
157-
) {
158-
Text(
159-
text = "Less Noise",
160-
style = TextStyle(
161-
fontSize = 14.sp,
162-
fontWeight = FontWeight.Light,
163-
color = labelTextColor
164-
),
165-
modifier = Modifier.padding(start = 4.dp)
166-
)
167-
Text(
168-
text = "More Noise",
169-
style = TextStyle(
170-
fontSize = 14.sp,
171-
fontWeight = FontWeight.Light,
172-
color = labelTextColor
173-
),
174-
modifier = Modifier.padding(end = 4.dp)
175-
)
176-
}
177107
}
178108
}
179109

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ fun CallControlSettings(hazeState: HazeState) {
287287
)
288288
}
289289

290-
DragSelectableDropdown(
290+
StyledDropdown(
291291
expanded = showSinglePressDropdown,
292292
onDismissRequest = {
293293
showSinglePressDropdown = false
@@ -415,7 +415,7 @@ fun CallControlSettings(hazeState: HazeState) {
415415
)
416416
}
417417

418-
DragSelectableDropdown(
418+
StyledDropdown(
419419
expanded = showDoublePressDropdown,
420420
onDismissRequest = {
421421
showDoublePressDropdown = false

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

Lines changed: 1 addition & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ fun MicrophoneSettings(hazeState: HazeState) {
269269
val microphoneAlwaysRightText = stringResource(R.string.microphone_always_right)
270270
val microphoneAlwaysLeftText = stringResource(R.string.microphone_always_left)
271271

272-
DragSelectableDropdown(
272+
StyledDropdown(
273273
expanded = showDropdown,
274274
onDismissRequest = {
275275
showDropdown = false
@@ -312,173 +312,3 @@ fun MicrophoneSettings(hazeState: HazeState) {
312312
fun MicrophoneSettingsPreview() {
313313
MicrophoneSettings(HazeState())
314314
}
315-
316-
@ExperimentalHazeMaterialsApi
317-
@Composable
318-
fun DragSelectableDropdown(
319-
expanded: Boolean,
320-
onDismissRequest: () -> Unit,
321-
options: List<String>,
322-
selectedOption: String,
323-
touchOffset: Offset?,
324-
boxPosition: Offset,
325-
onOptionSelected: (String) -> Unit,
326-
externalHoveredIndex: Int? = null,
327-
externalDragActive: Boolean = false,
328-
hazeState: HazeState,
329-
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier
330-
) {
331-
if (expanded) {
332-
val relativeOffset = touchOffset?.let { it - boxPosition } ?: Offset.Zero
333-
Popup(
334-
offset = IntOffset(relativeOffset.x.toInt(), relativeOffset.y.toInt()),
335-
onDismissRequest = onDismissRequest
336-
) {
337-
AnimatedVisibility(
338-
visible = true,
339-
enter = slideInVertically(initialOffsetY = { -it }) + fadeIn(),
340-
exit = slideOutVertically(targetOffsetY = { -it }) + fadeOut()
341-
) {
342-
Card(
343-
modifier = modifier
344-
.padding(8.dp)
345-
.width(300.dp)
346-
.background(Color.Transparent)
347-
.clip(RoundedCornerShape(8.dp)),
348-
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
349-
) {
350-
var hoveredIndex by remember { mutableStateOf<Int?>(null) }
351-
val itemHeight = 48.dp
352-
353-
var popupSize by remember { mutableStateOf(IntSize(0, 0)) }
354-
var lastDragPosition by remember { mutableStateOf<Offset?>(null) }
355-
356-
LaunchedEffect(externalHoveredIndex, externalDragActive) {
357-
if (externalDragActive) {
358-
hoveredIndex = externalHoveredIndex
359-
}
360-
}
361-
362-
Column(
363-
modifier = Modifier
364-
.onGloballyPositioned { coordinates ->
365-
popupSize = coordinates.size
366-
}
367-
.pointerInput(popupSize) {
368-
detectDragGestures(
369-
onDragStart = { offset ->
370-
hoveredIndex = (offset.y / itemHeight.toPx()).toInt()
371-
lastDragPosition = offset
372-
},
373-
onDrag = { change, _ ->
374-
val y = change.position.y
375-
hoveredIndex = (y / itemHeight.toPx()).toInt()
376-
lastDragPosition = change.position
377-
},
378-
onDragEnd = {
379-
val pos = lastDragPosition
380-
val withinBounds = pos != null &&
381-
pos.x >= 0f && pos.y >= 0f &&
382-
pos.x <= popupSize.width.toFloat() && pos.y <= popupSize.height.toFloat()
383-
384-
if (withinBounds) {
385-
hoveredIndex?.let { idx ->
386-
if (idx in options.indices) {
387-
onOptionSelected(options[idx])
388-
}
389-
}
390-
onDismissRequest()
391-
} else {
392-
hoveredIndex = null
393-
}
394-
}
395-
)
396-
}
397-
) {
398-
options.forEachIndexed { index, text ->
399-
val isHovered =
400-
if (externalDragActive && externalHoveredIndex != null) {
401-
index == externalHoveredIndex
402-
} else {
403-
index == hoveredIndex
404-
}
405-
val isSystemInDarkTheme = isSystemInDarkTheme()
406-
Box(
407-
modifier = Modifier
408-
.fillMaxWidth()
409-
.height(itemHeight)
410-
.background(
411-
Color.Transparent
412-
)
413-
.clickable(
414-
interactionSource = remember { MutableInteractionSource() },
415-
indication = null
416-
) {
417-
onOptionSelected(text)
418-
onDismissRequest()
419-
}
420-
.hazeEffect(
421-
state = hazeState,
422-
style = CupertinoMaterials.regular(),
423-
block = fun HazeEffectScope.() {
424-
alpha = 1f
425-
backgroundColor = if (isSystemInDarkTheme) {
426-
Color(0xB02C2C2E)
427-
} else {
428-
Color(0xB0FFFFFF)
429-
}
430-
tints = if (isHovered) listOf(
431-
HazeTint(
432-
color = if (isSystemInDarkTheme) Color(0x338A8A8A) else Color(0x40D9D9D9)
433-
)
434-
) else listOf()
435-
})
436-
.padding(horizontal = 12.dp),
437-
contentAlignment = Alignment.CenterStart
438-
) {
439-
Row(
440-
modifier = Modifier.fillMaxWidth(),
441-
horizontalArrangement = Arrangement.SpaceBetween,
442-
verticalAlignment = Alignment.CenterVertically
443-
) {
444-
Text(
445-
text,
446-
style = TextStyle(
447-
fontSize = 16.sp,
448-
color = if (isSystemInDarkTheme()) Color.White else Color.Black.copy(alpha = 0.75f),
449-
fontFamily = FontFamily(Font(R.font.sf_pro))
450-
)
451-
)
452-
Checkbox(
453-
checked = text == selectedOption,
454-
onCheckedChange = { onOptionSelected(text) },
455-
colors = CheckboxDefaults.colors().copy(
456-
checkedCheckmarkColor = Color(0xFF007AFF),
457-
uncheckedCheckmarkColor = Color.Transparent,
458-
checkedBoxColor = Color.Transparent,
459-
uncheckedBoxColor = Color.Transparent,
460-
checkedBorderColor = Color.Transparent,
461-
uncheckedBorderColor = Color.Transparent,
462-
disabledBorderColor = Color.Transparent,
463-
disabledCheckedBoxColor = Color.Transparent,
464-
disabledUncheckedBoxColor = Color.Transparent,
465-
disabledUncheckedBorderColor = Color.Transparent
466-
)
467-
)
468-
}
469-
}
470-
471-
if (index != options.lastIndex) {
472-
HorizontalDivider(
473-
thickness = 1.5.dp,
474-
color = Color(0x40888888),
475-
modifier = Modifier.padding(start = 12.dp, end = 0.dp)
476-
)
477-
}
478-
}
479-
}
480-
}
481-
}
482-
}
483-
}
484-
}

0 commit comments

Comments
 (0)