mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-02-10 19:52:24 +00:00
android: liquidglass, maybe?
the switch and icon button took quite a while. i forgot the order of modifiers matters!
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -51,22 +51,22 @@ fun AudioSettings(navController: NavController) {
|
|||||||
val textColor = if (isDarkTheme) Color.White else Color.Black
|
val textColor = if (isDarkTheme) Color.White else Color.Black
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.audio).uppercase(),
|
text = stringResource(R.string.audio),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f)
|
color = textColor.copy(alpha = 0.6f)
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
modifier = Modifier.padding(16.dp, bottom = 4.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(14.dp))
|
.clip(RoundedCornerShape(28.dp))
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
.padding(top = 2.dp)
|
.padding(top = 2.dp)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -76,11 +76,12 @@ fun AudioSettings(navController: NavController) {
|
|||||||
controlCommandIdentifier = AACPManager.Companion.ControlCommandIdentifiers.ADAPTIVE_VOLUME_CONFIG,
|
controlCommandIdentifier = AACPManager.Companion.ControlCommandIdentifiers.ADAPTIVE_VOLUME_CONFIG,
|
||||||
independent = false
|
independent = false
|
||||||
)
|
)
|
||||||
|
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp, end = 0.dp)
|
.padding(horizontal= 12.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
StyledToggle(
|
StyledToggle(
|
||||||
@@ -90,10 +91,10 @@ fun AudioSettings(navController: NavController) {
|
|||||||
independent = false
|
independent = false
|
||||||
)
|
)
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp, end = 0.dp)
|
.padding(horizontal= 12.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
StyledToggle(
|
StyledToggle(
|
||||||
@@ -103,10 +104,10 @@ fun AudioSettings(navController: NavController) {
|
|||||||
independent = false
|
independent = false
|
||||||
)
|
)
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp, end = 0.dp)
|
.padding(horizontal= 12.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
NavigationButton(
|
NavigationButton(
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ import androidx.compose.foundation.isSystemInDarkTheme
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -71,7 +73,6 @@ fun BatteryIndicator(
|
|||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(12.dp)
|
|
||||||
.background(backgroundColor), // just for haze to work
|
.background(backgroundColor), // just for haze to work
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
@@ -85,7 +86,7 @@ fun BatteryIndicator(
|
|||||||
color = batteryFillColor,
|
color = batteryFillColor,
|
||||||
gapSize = 0.dp,
|
gapSize = 0.dp,
|
||||||
strokeCap = StrokeCap.Round,
|
strokeCap = StrokeCap.Round,
|
||||||
strokeWidth = 2.dp,
|
strokeWidth = 4.dp,
|
||||||
trackColor = if (isDarkTheme) Color(0xFF0E0E0F) else Color(0xFFE3E3E8)
|
trackColor = if (isDarkTheme) Color(0xFF0E0E0F) else Color(0xFFE3E3E8)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -101,6 +102,8 @@ fun BatteryIndicator(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = "$prefix $batteryPercentage%",
|
text = "$prefix $batteryPercentage%",
|
||||||
color = batteryTextColor,
|
color = batteryTextColor,
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ fun BatteryView(service: AirPodsService, preview: Boolean = false) {
|
|||||||
contentDescription = stringResource(R.string.buds),
|
contentDescription = stringResource(R.string.buds),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(12.dp)
|
.padding(8.dp)
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
leftCharging == rightCharging &&
|
leftCharging == rightCharging &&
|
||||||
@@ -202,7 +202,7 @@ fun BatteryView(service: AirPodsService, preview: Boolean = false) {
|
|||||||
contentDescription = stringResource(R.string.case_alt),
|
contentDescription = stringResource(R.string.case_alt),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(12.dp)
|
.padding(8.dp)
|
||||||
)
|
)
|
||||||
if (caseLevel > 0 || case?.status != BatteryStatus.DISCONNECTED) {
|
if (caseLevel > 0 || case?.status != BatteryStatus.DISCONNECTED) {
|
||||||
BatteryIndicator(
|
BatteryIndicator(
|
||||||
|
|||||||
@@ -32,12 +32,8 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
@@ -57,6 +53,8 @@ import androidx.compose.ui.layout.positionInParent
|
|||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.Font
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -76,19 +74,19 @@ fun CallControlSettings(hazeState: HazeState) {
|
|||||||
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.call_controls).uppercase(),
|
text = stringResource(R.string.call_controls),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f)
|
color = textColor.copy(alpha = 0.6f)
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
modifier = Modifier.padding(16.dp, bottom = 4.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
.padding(top = 2.dp)
|
.padding(top = 2.dp)
|
||||||
) {
|
) {
|
||||||
val service = ServiceManager.getService()!!
|
val service = ServiceManager.getService()!!
|
||||||
@@ -169,8 +167,8 @@ fun CallControlSettings(hazeState: HazeState) {
|
|||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 12.dp, end = 12.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.height(50.dp),
|
.height(58.dp),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
@@ -187,17 +185,17 @@ fun CallControlSettings(hazeState: HazeState) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp, end = 0.dp)
|
.padding(horizontal = 12.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 12.dp, end = 12.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.height(50.dp)
|
.height(58.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures { offset ->
|
detectTapGestures { offset ->
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
@@ -276,14 +274,21 @@ fun CallControlSettings(hazeState: HazeState) {
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = singlePressAction,
|
text = singlePressAction,
|
||||||
fontSize = 16.sp,
|
style = TextStyle(
|
||||||
color = textColor.copy(alpha = 0.8f)
|
fontSize = 16.sp,
|
||||||
|
color = textColor.copy(alpha = 0.8f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
Icon(
|
Text(
|
||||||
Icons.Default.KeyboardArrowDown,
|
text = "",
|
||||||
contentDescription = null,
|
style = TextStyle(
|
||||||
modifier = Modifier.size(18.dp),
|
fontSize = 16.sp,
|
||||||
tint = textColor.copy(alpha = 0.6f)
|
color = textColor.copy(alpha = 0.6f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 6.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,17 +320,17 @@ fun CallControlSettings(hazeState: HazeState) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp, end = 0.dp)
|
.padding(horizontal = 12.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 12.dp, end = 12.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.height(50.dp)
|
.height(58.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures { offset ->
|
detectTapGestures { offset ->
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
@@ -404,14 +409,21 @@ fun CallControlSettings(hazeState: HazeState) {
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = doublePressAction,
|
text = doublePressAction,
|
||||||
fontSize = 16.sp,
|
style = TextStyle(
|
||||||
color = textColor.copy(alpha = 0.8f)
|
fontSize = 16.sp,
|
||||||
|
color = textColor.copy(alpha = 0.8f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
Icon(
|
Text(
|
||||||
Icons.Default.KeyboardArrowDown,
|
text = "",
|
||||||
contentDescription = null,
|
style = TextStyle(
|
||||||
modifier = Modifier.size(18.dp),
|
fontSize = 16.sp,
|
||||||
tint = textColor.copy(alpha = 0.6f)
|
color = textColor.copy(alpha = 0.6f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 6.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ import com.kyant.backdrop.effects.blur
|
|||||||
import com.kyant.backdrop.effects.colorControls
|
import com.kyant.backdrop.effects.colorControls
|
||||||
import com.kyant.backdrop.effects.refraction
|
import com.kyant.backdrop.effects.refraction
|
||||||
import com.kyant.backdrop.highlight.Highlight
|
import com.kyant.backdrop.highlight.Highlight
|
||||||
import com.kyant.backdrop.highlight.HighlightStyle
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.kavishdevar.librepods.R
|
import me.kavishdevar.librepods.R
|
||||||
import me.kavishdevar.librepods.utils.inspectDragGestures
|
import me.kavishdevar.librepods.utils.inspectDragGestures
|
||||||
@@ -143,7 +142,9 @@ half4 main(float2 coord) {
|
|||||||
.drawBackdrop(
|
.drawBackdrop(
|
||||||
backdrop,
|
backdrop,
|
||||||
{ RoundedCornerShape(48f.dp) },
|
{ RoundedCornerShape(48f.dp) },
|
||||||
highlight = { Highlight { HighlightStyle.Solid } },
|
highlight = {
|
||||||
|
Highlight.SolidDefault
|
||||||
|
},
|
||||||
onDrawSurface = { drawRect(containerColor) },
|
onDrawSurface = { drawRect(containerColor) },
|
||||||
effects = {
|
effects = {
|
||||||
colorControls(
|
colorControls(
|
||||||
@@ -153,7 +154,7 @@ half4 main(float2 coord) {
|
|||||||
blur(if (isLightTheme) 16f.dp.toPx() else 8f.dp.toPx())
|
blur(if (isLightTheme) 16f.dp.toPx() else 8f.dp.toPx())
|
||||||
refraction(24f.dp.toPx(), 48f.dp.toPx(), true)
|
refraction(24f.dp.toPx(), 48f.dp.toPx(), true)
|
||||||
},
|
},
|
||||||
layer = {
|
layerBlock = {
|
||||||
val width = size.width
|
val width = size.width
|
||||||
val height = size.height
|
val height = size.height
|
||||||
|
|
||||||
@@ -273,16 +274,6 @@ half4 main(float2 coord) {
|
|||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
// Box(
|
|
||||||
// Modifier
|
|
||||||
// .clip(RoundedCornerShape(50.dp))
|
|
||||||
// .background(containerColor.copy(0.2f))
|
|
||||||
// .clickable(onClick = onDismiss)
|
|
||||||
// .height(48.dp)
|
|
||||||
// .weight(1f)
|
|
||||||
// .padding(horizontal = 16.dp),
|
|
||||||
// contentAlignment = Alignment.Center
|
|
||||||
// ) {
|
|
||||||
StyledButton(
|
StyledButton(
|
||||||
onClick = onDismiss,
|
onClick = onDismiss,
|
||||||
backdrop = backdrop,
|
backdrop = backdrop,
|
||||||
@@ -295,16 +286,6 @@ half4 main(float2 coord) {
|
|||||||
style = TextStyle(contentColor, 16.sp)
|
style = TextStyle(contentColor, 16.sp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// Box(
|
|
||||||
// Modifier
|
|
||||||
// .clip(RoundedCornerShape(50.dp))
|
|
||||||
// .background(accentColor)
|
|
||||||
// .clickable(onClick = onConfirm)
|
|
||||||
// .height(48.dp)
|
|
||||||
// .weight(1f)
|
|
||||||
// .padding(horizontal = 16.dp),
|
|
||||||
// contentAlignment = Alignment.Center
|
|
||||||
// ) {
|
|
||||||
StyledButton(
|
StyledButton(
|
||||||
onClick = onConfirm,
|
onClick = onConfirm,
|
||||||
backdrop = backdrop,
|
backdrop = backdrop,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
package me.kavishdevar.librepods.composables
|
package me.kavishdevar.librepods.composables
|
||||||
|
|
||||||
|
import android.content.Context.MODE_PRIVATE
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -34,11 +35,9 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
|
||||||
import android.content.Context.MODE_PRIVATE
|
|
||||||
import me.kavishdevar.librepods.composables.StyledToggle
|
|
||||||
import me.kavishdevar.librepods.utils.AACPManager
|
|
||||||
import me.kavishdevar.librepods.R
|
import me.kavishdevar.librepods.R
|
||||||
|
import me.kavishdevar.librepods.utils.AACPManager
|
||||||
|
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ConnectionSettings() {
|
fun ConnectionSettings() {
|
||||||
@@ -48,7 +47,7 @@ fun ConnectionSettings() {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
.padding(top = 2.dp)
|
.padding(top = 2.dp)
|
||||||
) {
|
) {
|
||||||
StyledToggle(
|
StyledToggle(
|
||||||
@@ -59,10 +58,10 @@ fun ConnectionSettings() {
|
|||||||
independent = false
|
independent = false
|
||||||
)
|
)
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp, end = 0.dp)
|
.padding(horizontal= 12.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
StyledToggle(
|
StyledToggle(
|
||||||
|
|||||||
@@ -32,11 +32,7 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
@@ -55,6 +51,9 @@ import androidx.compose.ui.layout.onGloballyPositioned
|
|||||||
import androidx.compose.ui.layout.positionInParent
|
import androidx.compose.ui.layout.positionInParent
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.Font
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@@ -75,7 +74,7 @@ fun MicrophoneSettings(hazeState: HazeState) {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
.padding(top = 2.dp)
|
.padding(top = 2.dp)
|
||||||
) {
|
) {
|
||||||
val service = ServiceManager.getService()!!
|
val service = ServiceManager.getService()!!
|
||||||
@@ -141,8 +140,8 @@ fun MicrophoneSettings(hazeState: HazeState) {
|
|||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 12.dp, end = 12.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.height(55.dp)
|
.height(58.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures { offset ->
|
detectTapGestures { offset ->
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
@@ -214,8 +213,11 @@ fun MicrophoneSettings(hazeState: HazeState) {
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.microphone_mode),
|
text = stringResource(R.string.microphone_mode),
|
||||||
fontSize = 16.sp,
|
style = TextStyle(
|
||||||
color = textColor,
|
fontSize = 16.sp,
|
||||||
|
color = textColor,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
),
|
||||||
modifier = Modifier.padding(bottom = 4.dp)
|
modifier = Modifier.padding(bottom = 4.dp)
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
@@ -228,14 +230,21 @@ fun MicrophoneSettings(hazeState: HazeState) {
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = selectedMode,
|
text = selectedMode,
|
||||||
fontSize = 16.sp,
|
style = TextStyle(
|
||||||
color = textColor.copy(alpha = 0.8f)
|
fontSize = 16.sp,
|
||||||
|
color = textColor.copy(alpha = 0.8f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
Icon(
|
Text(
|
||||||
Icons.Default.KeyboardArrowDown,
|
text = "",
|
||||||
contentDescription = null,
|
style = TextStyle(
|
||||||
modifier = Modifier.size(16.dp),
|
fontSize = 16.sp,
|
||||||
tint = textColor.copy(alpha = 0.6f)
|
color = textColor.copy(alpha = 0.6f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 6.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
/*
|
|
||||||
* LibrePods - AirPods liberated from Apple’s ecosystem
|
|
||||||
*
|
|
||||||
* Copyright (C) 2025 LibrePods contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.kavishdevar.librepods.composables
|
|
||||||
|
|
||||||
import androidx.compose.animation.animateColorAsState
|
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
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.Modifier
|
|
||||||
import androidx.compose.ui.focus.onFocusChanged
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
|
||||||
import androidx.compose.ui.text.TextStyle
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import androidx.navigation.NavController
|
|
||||||
import androidx.navigation.compose.rememberNavController
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun NameField(
|
|
||||||
name: String,
|
|
||||||
value: String,
|
|
||||||
navController: NavController
|
|
||||||
) {
|
|
||||||
var isFocused by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
val isDarkTheme = isSystemInDarkTheme()
|
|
||||||
|
|
||||||
var backgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
|
||||||
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
|
||||||
|
|
||||||
val textColor = if (isDarkTheme) Color.White else Color.Black
|
|
||||||
val cursorColor = if (isFocused) {
|
|
||||||
if (isDarkTheme) Color.White else Color.Black
|
|
||||||
} else {
|
|
||||||
Color.Transparent
|
|
||||||
}
|
|
||||||
|
|
||||||
Box (
|
|
||||||
modifier = Modifier
|
|
||||||
.background(animatedBackgroundColor, RoundedCornerShape(14.dp))
|
|
||||||
.pointerInput(Unit) {
|
|
||||||
detectTapGestures(
|
|
||||||
onPress = {
|
|
||||||
backgroundColor = if (isDarkTheme) Color(0x40888888) else Color(0x40D9D9D9)
|
|
||||||
tryAwaitRelease()
|
|
||||||
backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
|
||||||
},
|
|
||||||
onTap = {
|
|
||||||
navController.navigate("rename")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(55.dp)
|
|
||||||
.background(
|
|
||||||
animatedBackgroundColor,
|
|
||||||
RoundedCornerShape(14.dp)
|
|
||||||
)
|
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
|
||||||
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = name,
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
)
|
|
||||||
BasicTextField(
|
|
||||||
value = value,
|
|
||||||
textStyle = TextStyle(
|
|
||||||
color = textColor.copy(alpha = 0.75f),
|
|
||||||
fontSize = 16.sp,
|
|
||||||
textAlign = TextAlign.End
|
|
||||||
),
|
|
||||||
onValueChange = {},
|
|
||||||
singleLine = true,
|
|
||||||
enabled = false,
|
|
||||||
cursorBrush = SolidColor(cursorColor),
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(start = 8.dp)
|
|
||||||
.onFocusChanged { focusState ->
|
|
||||||
isFocused = focusState.isFocused
|
|
||||||
},
|
|
||||||
decorationBox = { innerTextField ->
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.End
|
|
||||||
) {
|
|
||||||
innerTextField()
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
|
||||||
contentDescription = "Edit name",
|
|
||||||
tint = textColor.copy(alpha = 0.75f),
|
|
||||||
modifier = Modifier
|
|
||||||
.size(32.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview
|
|
||||||
@Composable
|
|
||||||
fun StyledTextFieldPreview() {
|
|
||||||
NameField(name = "Name", value = "AirPods Pro", rememberNavController())
|
|
||||||
}
|
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* LibrePods - AirPods liberated from Apple’s ecosystem
|
* LibrePods - AirPods liberated from Apple’s ecosystem
|
||||||
*
|
*
|
||||||
* Copyright (C) 2025 LibrePods contributors
|
* Copyright (C) 2025 LibrePods contributors
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
* it under the terms of the GNU Affero General Public License as published
|
||||||
* by the Free Software Foundation, either version 3 of the License.
|
* by the Free Software Foundation, either version 3 of the License.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Affero General Public License for more details.
|
* GNU Affero General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -23,75 +23,105 @@ import androidx.compose.animation.core.tween
|
|||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowRight
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.IconButtonDefaults
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.Font
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import me.kavishdevar.librepods.R
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NavigationButton(to: String, name: String, navController: NavController, onClick: (() -> Unit)? = null, independent: Boolean = true) {
|
fun NavigationButton(
|
||||||
|
to: String,
|
||||||
|
name: String,
|
||||||
|
navController: NavController, onClick: (() -> Unit)? = null,
|
||||||
|
independent: Boolean = true,
|
||||||
|
description: String? = null,
|
||||||
|
currentState: String? = null
|
||||||
|
) {
|
||||||
val isDarkTheme = isSystemInDarkTheme()
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
var backgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
var backgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
||||||
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
||||||
|
Column {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(animatedBackgroundColor, RoundedCornerShape(if (independent) 14.dp else 0.dp))
|
.background(animatedBackgroundColor, RoundedCornerShape(if (independent) 28.dp else 0.dp))
|
||||||
.height(55.dp)
|
.height(58.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onPress = {
|
onPress = {
|
||||||
backgroundColor = if (isDarkTheme) Color(0x40888888) else Color(0x40D9D9D9)
|
backgroundColor = if (isDarkTheme) Color(0x40888888) else Color(0x40D9D9D9)
|
||||||
tryAwaitRelease()
|
tryAwaitRelease()
|
||||||
backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
},
|
},
|
||||||
onTap = {
|
onTap = {
|
||||||
if (onClick != null) onClick() else navController.navigate(to)
|
if (onClick != null) onClick() else navController.navigate(to)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = name,
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
color = if (isDarkTheme) Color.White else Color.Black,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
if (currentState != null) {
|
||||||
|
Text(
|
||||||
|
text = currentState,
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(alpha = 0.8f),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
Text(
|
||||||
Text(
|
text = "",
|
||||||
text = name,
|
style = TextStyle(
|
||||||
modifier = Modifier.padding(16.dp),
|
fontSize = 16.sp,
|
||||||
color = if (isDarkTheme) Color.White else Color.Black
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
)
|
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(alpha = 0.6f)
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
),
|
||||||
IconButton(
|
modifier = Modifier
|
||||||
onClick = { if (onClick != null) onClick() else navController.navigate(to) },
|
.padding(start = if (currentState != null) 6.dp else 0.dp)
|
||||||
colors = IconButtonDefaults.iconButtonColors(
|
)
|
||||||
containerColor = Color.Transparent,
|
}
|
||||||
contentColor = if (isDarkTheme) Color.White else Color.Black
|
if (description != null) {
|
||||||
),
|
Text(
|
||||||
modifier = Modifier
|
text = description,
|
||||||
.padding(start = 16.dp)
|
style = TextStyle(
|
||||||
.fillMaxHeight()
|
fontSize = 12.sp,
|
||||||
) {
|
fontWeight = FontWeight.Light,
|
||||||
@Suppress("DEPRECATION")
|
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(alpha = 0.6f),
|
||||||
Icon(
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
imageVector = Icons.Default.KeyboardArrowRight,
|
),
|
||||||
contentDescription = name
|
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,4 +131,4 @@ fun NavigationButton(to: String, name: String, navController: NavController, onC
|
|||||||
@Composable
|
@Composable
|
||||||
fun NavigationButtonPreview() {
|
fun NavigationButtonPreview() {
|
||||||
NavigationButton("to", "Name", NavController(LocalContext.current))
|
NavigationButton("to", "Name", NavController(LocalContext.current))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,10 +181,10 @@ fun NoiseControlSettings(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.noise_control).uppercase(),
|
text = stringResource(R.string.noise_control),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f),
|
color = textColor.copy(alpha = 0.6f),
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
||||||
@@ -241,7 +241,7 @@ fun NoiseControlSettings(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(60.dp)
|
.height(60.dp)
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
@@ -334,7 +334,7 @@ fun NoiseControlSettings(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(3.dp)
|
.padding(3.dp)
|
||||||
.background(selectedBackground, RoundedCornerShape(12.dp))
|
.background(selectedBackground, RoundedCornerShape(26.dp))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +400,6 @@ fun NoiseControlSettings(
|
|||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 4.dp)
|
|
||||||
.padding(top = 4.dp)
|
.padding(top = 4.dp)
|
||||||
) {
|
) {
|
||||||
if (offListeningMode.value) {
|
if (offListeningMode.value) {
|
||||||
@@ -408,7 +407,6 @@ fun NoiseControlSettings(
|
|||||||
text = stringResource(R.string.off),
|
text = stringResource(R.string.off),
|
||||||
style = TextStyle(fontSize = 12.sp, color = textColor),
|
style = TextStyle(fontSize = 12.sp, color = textColor),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -416,21 +414,18 @@ fun NoiseControlSettings(
|
|||||||
text = stringResource(R.string.transparency),
|
text = stringResource(R.string.transparency),
|
||||||
style = TextStyle(fontSize = 12.sp, color = textColor),
|
style = TextStyle(fontSize = 12.sp, color = textColor),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.adaptive),
|
text = stringResource(R.string.adaptive),
|
||||||
style = TextStyle(fontSize = 12.sp, color = textColor),
|
style = TextStyle(fontSize = 12.sp, color = textColor),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.noise_cancellation),
|
text = stringResource(R.string.noise_cancellation),
|
||||||
style = TextStyle(fontSize = 12.sp, color = textColor),
|
style = TextStyle(fontSize = 12.sp, color = textColor),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,34 +19,21 @@
|
|||||||
package me.kavishdevar.librepods.composables
|
package me.kavishdevar.librepods.composables
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.compose.animation.animateColorAsState
|
import android.content.res.Configuration
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
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.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
@@ -65,12 +52,6 @@ fun PressAndHoldSettings(navController: NavController) {
|
|||||||
val isDarkTheme = isSystemInDarkTheme()
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
val textColor = if (isDarkTheme) Color.White else Color.Black
|
val textColor = if (isDarkTheme) Color.White else Color.Black
|
||||||
val dividerColor = Color(0x40888888)
|
val dividerColor = Color(0x40888888)
|
||||||
var leftBackgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
|
||||||
var rightBackgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
|
||||||
|
|
||||||
val animationSpec = tween<Color>(durationMillis = 500)
|
|
||||||
val animatedLeftBackgroundColor by animateColorAsState(targetValue = leftBackgroundColor, animationSpec = animationSpec)
|
|
||||||
val animatedRightBackgroundColor by animateColorAsState(targetValue = rightBackgroundColor, animationSpec = animationSpec)
|
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
val sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
@@ -91,14 +72,14 @@ fun PressAndHoldSettings(navController: NavController) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.press_and_hold_airpods).uppercase(),
|
text = stringResource(R.string.press_and_hold_airpods),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f),
|
color = textColor.copy(alpha = 0.6f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
modifier = Modifier.padding(16.dp, bottom = 4.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(1.dp))
|
Spacer(modifier = Modifier.height(1.dp))
|
||||||
@@ -106,126 +87,33 @@ fun PressAndHoldSettings(navController: NavController) {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF), RoundedCornerShape(14.dp))
|
.background(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF), RoundedCornerShape(28.dp))
|
||||||
|
.clip(RoundedCornerShape(28.dp))
|
||||||
) {
|
) {
|
||||||
Box(
|
NavigationButton(
|
||||||
modifier = Modifier
|
to = "long_press/Left",
|
||||||
.fillMaxWidth()
|
name = stringResource(R.string.left),
|
||||||
.height(50.dp)
|
navController = navController,
|
||||||
.background(animatedLeftBackgroundColor, RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp))
|
independent = false,
|
||||||
.pointerInput(Unit) {
|
currentState = leftActionText,
|
||||||
detectTapGestures(
|
)
|
||||||
onPress = {
|
|
||||||
leftBackgroundColor = dividerColor
|
|
||||||
tryAwaitRelease()
|
|
||||||
leftBackgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
|
||||||
},
|
|
||||||
onTap = {
|
|
||||||
navController.navigate("long_press/Left")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(start = 16.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.left),
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
),
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
|
||||||
Text(
|
|
||||||
text = leftActionText,
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor.copy(alpha = 0.6f),
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
),
|
|
||||||
)
|
|
||||||
IconButton(
|
|
||||||
onClick = {
|
|
||||||
navController.navigate("long_press/Left")
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
|
||||||
contentDescription = "go",
|
|
||||||
tint = textColor
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = dividerColor,
|
color = dividerColor,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
|
)
|
||||||
|
NavigationButton(
|
||||||
|
to = "long_press/Right",
|
||||||
|
name = stringResource(R.string.right),
|
||||||
|
navController = navController,
|
||||||
|
independent = false,
|
||||||
|
currentState = rightActionText,
|
||||||
)
|
)
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(50.dp)
|
|
||||||
.background(animatedRightBackgroundColor, RoundedCornerShape(bottomEnd = 14.dp, bottomStart = 14.dp))
|
|
||||||
.pointerInput(Unit) {
|
|
||||||
detectTapGestures(
|
|
||||||
onPress = {
|
|
||||||
rightBackgroundColor = dividerColor
|
|
||||||
tryAwaitRelease()
|
|
||||||
rightBackgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
|
||||||
},
|
|
||||||
onTap = {
|
|
||||||
navController.navigate("long_press/Right")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(start = 16.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.right),
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
),
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
|
||||||
Text(
|
|
||||||
text = rightActionText,
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor.copy(alpha = 0.6f),
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
),
|
|
||||||
)
|
|
||||||
IconButton(
|
|
||||||
onClick = {
|
|
||||||
navController.navigate("long_press/Right")
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
|
||||||
contentDescription = "go",
|
|
||||||
tint = textColor
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
@Composable
|
@Composable
|
||||||
fun PressAndHoldSettingsPreview() {
|
fun PressAndHoldSettingsPreview() {
|
||||||
PressAndHoldSettings(navController = NavController(LocalContext.current))
|
PressAndHoldSettings(navController = NavController(LocalContext.current))
|
||||||
|
|||||||
@@ -74,7 +74,8 @@ fun StyledButton(
|
|||||||
isInteractive: Boolean = true,
|
isInteractive: Boolean = true,
|
||||||
tint: Color = Color.Unspecified,
|
tint: Color = Color.Unspecified,
|
||||||
surfaceColor: Color = Color.Unspecified,
|
surfaceColor: Color = Color.Unspecified,
|
||||||
content: @Composable RowScope.() -> Unit
|
maxScale: Float = 0.1f,
|
||||||
|
content: @Composable RowScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
val animationScope = rememberCoroutineScope()
|
val animationScope = rememberCoroutineScope()
|
||||||
val progressAnimation = remember { Animatable(0f) }
|
val progressAnimation = remember { Animatable(0f) }
|
||||||
@@ -113,7 +114,7 @@ half4 main(float2 coord) {
|
|||||||
effects = {
|
effects = {
|
||||||
blur(16f.dp.toPx())
|
blur(16f.dp.toPx())
|
||||||
},
|
},
|
||||||
layer = null,
|
layerBlock = null,
|
||||||
onDrawSurface = {
|
onDrawSurface = {
|
||||||
if (tint.isSpecified) {
|
if (tint.isSpecified) {
|
||||||
drawRect(tint, blendMode = BlendMode.Hue)
|
drawRect(tint, blendMode = BlendMode.Hue)
|
||||||
@@ -147,12 +148,11 @@ half4 main(float2 coord) {
|
|||||||
blur(2f.dp.toPx())
|
blur(2f.dp.toPx())
|
||||||
refraction(12f.dp.toPx(), 24f.dp.toPx())
|
refraction(12f.dp.toPx(), 24f.dp.toPx())
|
||||||
},
|
},
|
||||||
layer = {
|
layerBlock = {
|
||||||
val width = size.width
|
val width = size.width
|
||||||
val height = size.height
|
val height = size.height
|
||||||
|
|
||||||
val progress = progressAnimation.value
|
val progress = progressAnimation.value
|
||||||
val maxScale = 0.1f
|
|
||||||
val scale = lerp(1f, 1f + maxScale, progress)
|
val scale = lerp(1f, 1f + maxScale, progress)
|
||||||
|
|
||||||
val maxOffset = size.minDimension
|
val maxOffset = size.minDimension
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ fun StyledDropdown(
|
|||||||
|
|
||||||
if (index != options.lastIndex) {
|
if (index != options.lastIndex) {
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier.padding(start = 12.dp, end = 0.dp)
|
modifier = Modifier.padding(start = 12.dp, end = 0.dp)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import androidx.compose.animation.core.Animatable
|
|||||||
import androidx.compose.animation.core.VectorConverter
|
import androidx.compose.animation.core.VectorConverter
|
||||||
import androidx.compose.animation.core.VisibilityThreshold
|
import androidx.compose.animation.core.VisibilityThreshold
|
||||||
import androidx.compose.animation.core.spring
|
import androidx.compose.animation.core.spring
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
@@ -59,8 +60,10 @@ import androidx.compose.ui.unit.sp
|
|||||||
import androidx.compose.ui.util.fastCoerceAtMost
|
import androidx.compose.ui.util.fastCoerceAtMost
|
||||||
import androidx.compose.ui.util.fastCoerceIn
|
import androidx.compose.ui.util.fastCoerceIn
|
||||||
import androidx.compose.ui.util.lerp
|
import androidx.compose.ui.util.lerp
|
||||||
|
import com.kyant.backdrop.backdrops.LayerBackdrop
|
||||||
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import com.kyant.backdrop.drawBackdrop
|
import com.kyant.backdrop.drawBackdrop
|
||||||
|
import com.kyant.backdrop.effects.blur
|
||||||
import com.kyant.backdrop.effects.refractionWithDispersion
|
import com.kyant.backdrop.effects.refractionWithDispersion
|
||||||
import com.kyant.backdrop.highlight.Highlight
|
import com.kyant.backdrop.highlight.Highlight
|
||||||
import com.kyant.backdrop.shadow.Shadow
|
import com.kyant.backdrop.shadow.Shadow
|
||||||
@@ -79,6 +82,8 @@ fun StyledIconButton(
|
|||||||
icon: String,
|
icon: String,
|
||||||
darkMode: Boolean,
|
darkMode: Boolean,
|
||||||
tint: Color = Color.Unspecified,
|
tint: Color = Color.Unspecified,
|
||||||
|
backdrop: LayerBackdrop = rememberLayerBackdrop(),
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val animationScope = rememberCoroutineScope()
|
val animationScope = rememberCoroutineScope()
|
||||||
val progressAnimationSpec = spring(0.5f, 300f, 0.001f)
|
val progressAnimationSpec = spring(0.5f, 300f, 0.001f)
|
||||||
@@ -110,26 +115,23 @@ half4 main(float2 coord) {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
shape = RoundedCornerShape(56.dp),
|
shape = RoundedCornerShape(56.dp),
|
||||||
modifier = Modifier
|
modifier = modifier
|
||||||
.padding(horizontal = 12.dp)
|
.padding(horizontal = 12.dp)
|
||||||
.drawBackdrop(
|
.drawBackdrop(
|
||||||
backdrop = rememberLayerBackdrop(),
|
backdrop = backdrop,
|
||||||
shape = { RoundedCornerShape(56.dp) },
|
shape = { RoundedCornerShape(56.dp) },
|
||||||
highlight = {
|
highlight = { Highlight.AmbientDefault.copy(alpha = if (isDarkTheme) 1f else 0f) },
|
||||||
val progress = progressAnimation.value
|
|
||||||
Highlight.AmbientDefault.copy(alpha = progress.coerceIn(0.45f, 1f))
|
|
||||||
},
|
|
||||||
shadow = {
|
shadow = {
|
||||||
Shadow(
|
Shadow(
|
||||||
radius = 4f.dp,
|
radius = 48f.dp,
|
||||||
color = Color.Black.copy(0.08f)
|
color = Color.Black.copy(if (isDarkTheme) 0.08f else 0.4f)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
layer = {
|
layerBlock = {
|
||||||
val width = size.width
|
val width = size.width
|
||||||
val height = size.height
|
val height = size.height
|
||||||
|
|
||||||
@@ -182,7 +184,7 @@ half4 main(float2 coord) {
|
|||||||
drawLayer(innerShadowLayer)
|
drawLayer(innerShadowLayer)
|
||||||
|
|
||||||
drawRect(
|
drawRect(
|
||||||
Color.White.copy(progress.coerceIn(0.15f, 0.35f))
|
(if (isDarkTheme) Color(0xFFAFAFAF) else Color.White).copy(progress.coerceIn(0.15f, 0.35f))
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onDrawFront = {
|
onDrawFront = {
|
||||||
@@ -218,6 +220,7 @@ half4 main(float2 coord) {
|
|||||||
},
|
},
|
||||||
effects = {
|
effects = {
|
||||||
refractionWithDispersion(6f.dp.toPx(), size.height / 2f)
|
refractionWithDispersion(6f.dp.toPx(), size.height / 2f)
|
||||||
|
blur(24f, TileMode.Decal)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.pointerInput(animationScope) {
|
.pointerInput(animationScope) {
|
||||||
|
|||||||
@@ -31,12 +31,14 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.heightIn
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -84,6 +86,7 @@ import com.kyant.backdrop.highlight.Highlight
|
|||||||
import com.kyant.backdrop.shadow.Shadow
|
import com.kyant.backdrop.shadow.Shadow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.kavishdevar.librepods.R
|
import me.kavishdevar.librepods.R
|
||||||
|
import kotlin.math.abs
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -136,23 +139,26 @@ fun StyledSlider(
|
|||||||
|
|
||||||
val content = @Composable {
|
val content = @Composable {
|
||||||
Box(
|
Box(
|
||||||
Modifier.fillMaxWidth(if (startIcon == null && endIcon == null) 0.95f else 1f)
|
Modifier
|
||||||
) {
|
.fillMaxWidth(if (startIcon == null && endIcon == null) 0.95f else 1f)
|
||||||
|
) {
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
|
.padding(vertical = 4.dp)
|
||||||
.layerBackdrop(sliderBackdrop)
|
.layerBackdrop(sliderBackdrop)
|
||||||
.fillMaxWidth()) {
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth(1f)
|
.fillMaxWidth(1f)
|
||||||
.padding(vertical = 12.dp),
|
.padding(vertical = 12.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
|
||||||
) {
|
) {
|
||||||
if (startLabel != null || endLabel != null) {
|
if (startLabel != null || endLabel != null) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 8.dp),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
@@ -174,80 +180,119 @@ fun StyledSlider(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
}
|
}
|
||||||
|
Column(
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 4.dp)
|
.padding(vertical = 4.dp)
|
||||||
.then(if (startIcon == null && endIcon == null) Modifier.padding(horizontal = 12.dp) else Modifier),
|
.then(if (startIcon == null && endIcon == null) Modifier.padding(horizontal = 8.dp) else Modifier),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(0.dp)
|
|
||||||
) {
|
) {
|
||||||
if (startIcon != null) {
|
Row(
|
||||||
Text(
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
text = startIcon,
|
horizontalArrangement = Arrangement.spacedBy(0.dp)
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 18.sp,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
color = accentColor,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
),
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(horizontal = 12.dp)
|
|
||||||
.onGloballyPositioned {
|
|
||||||
startIconWidthState.floatValue = it.size.width.toFloat()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Box(
|
|
||||||
Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.onSizeChanged { trackWidthState.floatValue = it.width.toFloat() }
|
|
||||||
.onGloballyPositioned {
|
|
||||||
trackPositionState.floatValue =
|
|
||||||
it.positionInParent().y + it.size.height / 2f
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
Box(
|
if (startIcon != null) {
|
||||||
Modifier
|
Text(
|
||||||
.clip(RoundedCornerShape(28.dp))
|
text = startIcon,
|
||||||
.background(trackColor)
|
style = TextStyle(
|
||||||
.height(6f.dp)
|
fontSize = 18.sp,
|
||||||
.fillMaxWidth()
|
fontWeight = FontWeight.Normal,
|
||||||
)
|
color = accentColor,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
Box(
|
),
|
||||||
Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(28.dp))
|
.padding(horizontal = 12.dp)
|
||||||
.background(accentColor)
|
.onGloballyPositioned {
|
||||||
.height(6f.dp)
|
startIconWidthState.floatValue = it.size.width.toFloat()
|
||||||
.layout { measurable, constraints ->
|
|
||||||
val placeable = measurable.measure(constraints)
|
|
||||||
val fraction = fraction
|
|
||||||
val width =
|
|
||||||
(fraction * constraints.maxWidth).fastRoundToInt()
|
|
||||||
layout(width, placeable.height) {
|
|
||||||
placeable.place(0, 0)
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
}
|
||||||
}
|
Box(
|
||||||
if (endIcon != null) {
|
Modifier
|
||||||
Text(
|
.weight(1f)
|
||||||
text = endIcon,
|
.onSizeChanged { trackWidthState.floatValue = it.width.toFloat() }
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 18.sp,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
color = accentColor,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
),
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(horizontal = 12.dp)
|
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
endIconWidthState.floatValue = it.size.width.toFloat()
|
trackPositionState.floatValue =
|
||||||
|
it.positionInParent().y + it.size.height / 2f
|
||||||
}
|
}
|
||||||
)
|
) {
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.clip(RoundedCornerShape(28.dp))
|
||||||
|
.background(trackColor)
|
||||||
|
.height(6f.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.clip(RoundedCornerShape(28.dp))
|
||||||
|
.background(accentColor)
|
||||||
|
.height(6f.dp)
|
||||||
|
.layout { measurable, constraints ->
|
||||||
|
val placeable = measurable.measure(constraints)
|
||||||
|
val fraction = fraction
|
||||||
|
val width =
|
||||||
|
(fraction * constraints.maxWidth).fastRoundToInt()
|
||||||
|
layout(width, placeable.height) {
|
||||||
|
placeable.place(0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (endIcon != null) {
|
||||||
|
Text(
|
||||||
|
text = endIcon,
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
color = accentColor,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 12.dp)
|
||||||
|
.onGloballyPositioned {
|
||||||
|
endIconWidthState.floatValue = it.size.width.toFloat()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (snapPoints.isNotEmpty() && startLabel != null && endLabel != null) Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
if (snapPoints.isNotEmpty()) {
|
||||||
|
val trackWidth = if (startIcon != null && endIcon != null) trackWidthState.floatValue - with(density) { 6.dp.toPx() } * 2 else trackWidthState.floatValue- with(density) { 22.dp.toPx() }
|
||||||
|
val startOffset =
|
||||||
|
if (startIcon != null) startIconWidthState.floatValue + with(
|
||||||
|
density
|
||||||
|
) { 34.dp.toPx() } else with(density) { 14.dp.toPx() }
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
snapPoints.forEach { point ->
|
||||||
|
val pointFraction =
|
||||||
|
((point - valueRange.start) / (valueRange.endInclusive - valueRange.start))
|
||||||
|
.fastCoerceIn(0f, 1f)
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.graphicsLayer {
|
||||||
|
translationX =
|
||||||
|
startOffset + pointFraction * trackWidth - 4.dp.toPx()
|
||||||
|
}
|
||||||
|
.size(2.dp)
|
||||||
|
.background(
|
||||||
|
trackColor,
|
||||||
|
CircleShape
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,10 +302,10 @@ fun StyledSlider(
|
|||||||
Modifier
|
Modifier
|
||||||
.graphicsLayer {
|
.graphicsLayer {
|
||||||
val startOffset =
|
val startOffset =
|
||||||
if (startIcon != null) startIconWidthState.floatValue + with(density) { 24.dp.toPx() } else with(density) { 8.dp.toPx() }
|
if (startIcon != null) startIconWidthState.floatValue + with(density) { 24.dp.toPx() } else with(density) { 12.dp.toPx() }
|
||||||
translationX =
|
translationX =
|
||||||
startOffset + fraction * trackWidthState.floatValue - size.width / 2f
|
startOffset + fraction * trackWidthState.floatValue - size.width / 2f
|
||||||
translationY = if (startLabel != null || endLabel != null) trackPositionState.floatValue + with(density) { 22.dp.toPx() } + size.height / 2f else trackPositionState.floatValue + with(density) { 4.dp.toPx() }
|
translationY = if (startLabel != null || endLabel != null) trackPositionState.floatValue + with(density) { 26.dp.toPx() } + size.height / 2f else trackPositionState.floatValue + with(density) { 8.dp.toPx() }
|
||||||
}
|
}
|
||||||
.draggable(
|
.draggable(
|
||||||
rememberDraggableState { delta ->
|
rememberDraggableState { delta ->
|
||||||
@@ -305,7 +350,7 @@ fun StyledSlider(
|
|||||||
color = Color.Black.copy(0.05f)
|
color = Color.Black.copy(0.05f)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
layer = {
|
layerBlock = {
|
||||||
val progress = progressAnimation.value
|
val progress = progressAnimation.value
|
||||||
val scale = lerp(1f, 1.5f, progress)
|
val scale = lerp(1f, 1.5f, progress)
|
||||||
scaleX = scale
|
scaleX = scale
|
||||||
@@ -361,20 +406,20 @@ fun StyledSlider(
|
|||||||
text = label,
|
text = label,
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = labelTextColor.copy(alpha = 0.6f),
|
color = labelTextColor.copy(alpha = 0.6f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp)
|
modifier = Modifier.padding(horizontal = 18.dp, vertical = 4.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
.padding(horizontal = 8.dp, vertical = 0.dp)
|
.padding(horizontal = 8.dp, vertical = 0.dp)
|
||||||
.heightIn(min = 55.dp),
|
.heightIn(min = 58.dp),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
content()
|
content()
|
||||||
@@ -390,7 +435,7 @@ fun StyledSlider(
|
|||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 12.dp, vertical = 4.dp)
|
.padding(horizontal = 18.dp, vertical = 4.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -402,8 +447,8 @@ fun StyledSlider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun snapIfClose(value: Float, points: List<Float>, threshold: Float = 0.05f): Float {
|
private fun snapIfClose(value: Float, points: List<Float>, threshold: Float = 0.05f): Float {
|
||||||
val nearest = points.minByOrNull { kotlin.math.abs(it - value) } ?: value
|
val nearest = points.minByOrNull { abs(it - value) } ?: value
|
||||||
return if (kotlin.math.abs(nearest - value) <= threshold) nearest else value
|
return if (abs(nearest - value) <= threshold) nearest else value
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
@@ -426,9 +471,11 @@ fun StyledSliderPreview() {
|
|||||||
a.floatValue = it
|
a.floatValue = it
|
||||||
},
|
},
|
||||||
valueRange = 0f..2f,
|
valueRange = 0f..2f,
|
||||||
|
snapPoints = listOf(0f, 0.5f, 1f, 1.5f, 2f),
|
||||||
|
snapThreshold = 0.1f,
|
||||||
independent = true,
|
independent = true,
|
||||||
startLabel = "A",
|
startLabel = "A",
|
||||||
endLabel = "B"
|
endLabel = "B",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,8 +48,11 @@ import androidx.compose.ui.draw.clip
|
|||||||
import androidx.compose.ui.graphics.BlendMode
|
import androidx.compose.ui.graphics.BlendMode
|
||||||
import androidx.compose.ui.graphics.BlurEffect
|
import androidx.compose.ui.graphics.BlurEffect
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Paint
|
||||||
import androidx.compose.ui.graphics.TileMode
|
import androidx.compose.ui.graphics.TileMode
|
||||||
import androidx.compose.ui.graphics.drawOutline
|
import androidx.compose.ui.graphics.drawOutline
|
||||||
|
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
|
||||||
|
import androidx.compose.ui.graphics.drawscope.scale
|
||||||
import androidx.compose.ui.graphics.drawscope.translate
|
import androidx.compose.ui.graphics.drawscope.translate
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.graphics.layer.CompositingStrategy
|
import androidx.compose.ui.graphics.layer.CompositingStrategy
|
||||||
@@ -68,7 +71,7 @@ import com.kyant.backdrop.drawBackdrop
|
|||||||
import com.kyant.backdrop.effects.refractionWithDispersion
|
import com.kyant.backdrop.effects.refractionWithDispersion
|
||||||
import com.kyant.backdrop.highlight.Highlight
|
import com.kyant.backdrop.highlight.Highlight
|
||||||
import com.kyant.backdrop.shadow.Shadow
|
import com.kyant.backdrop.shadow.Shadow
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -76,16 +79,17 @@ fun StyledSwitch(
|
|||||||
checked: Boolean,
|
checked: Boolean,
|
||||||
onCheckedChange: (Boolean) -> Unit,
|
onCheckedChange: (Boolean) -> Unit,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
|
indpendent: Boolean = true,
|
||||||
) {
|
) {
|
||||||
val isDarkTheme = isSystemInDarkTheme()
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
|
|
||||||
val onColor = if (enabled) Color(0xFF34C759) else if (isDarkTheme) Color(0xFF5B5B5E) else Color(0xFFD1D1D6)
|
val onColor = if (enabled) Color(0xFF34C759) else if (isDarkTheme) Color(0xFF5B5B5E) else Color(0xFFD1D1D6)
|
||||||
val offColor = if (enabled) if (isDarkTheme) Color(0xFF5B5B5E) else Color(0xFFD1D1D6) else if (isDarkTheme) Color(0xFF5B5B5E) else Color(0xFFD1D1D6)
|
val offColor = if (enabled) if (isDarkTheme) Color(0xFF5B5B5E) else Color(0xFFD1D1D6) else if (isDarkTheme) Color(0xFF5B5B5E) else Color(0xFFD1D1D6)
|
||||||
|
|
||||||
val trackWidth = 70.dp
|
val trackWidth = 64.dp
|
||||||
val trackHeight = 31.dp
|
val trackHeight = 28.dp
|
||||||
val thumbHeight = 27.dp
|
val thumbHeight = 24.dp
|
||||||
val thumbWidth = 36.dp
|
val thumbWidth = 39.dp
|
||||||
|
|
||||||
val backdrop = rememberLayerBackdrop()
|
val backdrop = rememberLayerBackdrop()
|
||||||
val switchBackdrop = rememberLayerBackdrop()
|
val switchBackdrop = rememberLayerBackdrop()
|
||||||
@@ -97,18 +101,23 @@ fun StyledSwitch(
|
|||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val animationScope = rememberCoroutineScope()
|
val animationScope = rememberCoroutineScope()
|
||||||
val progressAnimationSpec = spring(0.5f, 300f, 0.001f)
|
val progressAnimationSpec = spring(0.5f, 300f, 0.001f)
|
||||||
val colorAnimationSpec = tween<Color>(300, easing = FastOutSlowInEasing)
|
val colorAnimationSpec = tween<Color>(200, easing = FastOutSlowInEasing)
|
||||||
val progressAnimation = remember { Animatable(0f) }
|
val progressAnimation = remember { Animatable(0f) }
|
||||||
val innerShadowLayer = rememberGraphicsLayer().apply {
|
val innerShadowLayer = rememberGraphicsLayer().apply {
|
||||||
compositingStrategy = CompositingStrategy.Offscreen
|
compositingStrategy = CompositingStrategy.Offscreen
|
||||||
}
|
}
|
||||||
val animatedTrackColor = remember { Animatable(if (checked) onColor else offColor) }
|
val animatedTrackColor = remember { Animatable(if (checked) onColor else offColor) }
|
||||||
|
|
||||||
LaunchedEffect(checked) {
|
LaunchedEffect(checked) {
|
||||||
val targetColor = if (checked) onColor else offColor
|
coroutineScope {
|
||||||
animatedTrackColor.animateTo(targetColor, colorAnimationSpec)
|
launch {
|
||||||
val targetFrac = if (checked) 1f else 0f
|
val targetColor = if (checked) onColor else offColor
|
||||||
animatedFraction.animateTo(targetFrac, progressAnimationSpec)
|
animatedTrackColor.animateTo(targetColor, colorAnimationSpec)
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
val targetFrac = if (checked) 1f else 0f
|
||||||
|
animatedFraction.animateTo(targetFrac, progressAnimationSpec)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
@@ -136,7 +145,7 @@ fun StyledSwitch(
|
|||||||
.then(if (enabled) Modifier.draggable(
|
.then(if (enabled) Modifier.draggable(
|
||||||
rememberDraggableState { delta ->
|
rememberDraggableState { delta ->
|
||||||
if (trackWidthPx.floatValue > 0f) {
|
if (trackWidthPx.floatValue > 0f) {
|
||||||
val newFraction = (animatedFraction.value + delta / trackWidthPx.floatValue).fastCoerceIn(0f, 1f)
|
val newFraction = (animatedFraction.value + delta / trackWidthPx.floatValue).fastCoerceIn(-0.3f, 1.3f)
|
||||||
animationScope.launch {
|
animationScope.launch {
|
||||||
animatedFraction.snapTo(newFraction)
|
animatedFraction.snapTo(newFraction)
|
||||||
}
|
}
|
||||||
@@ -155,10 +164,12 @@ fun StyledSwitch(
|
|||||||
},
|
},
|
||||||
onDragStopped = {
|
onDragStopped = {
|
||||||
animationScope.launch {
|
animationScope.launch {
|
||||||
progressAnimation.animateTo(0f, progressAnimationSpec)
|
|
||||||
val snappedFraction = if (animatedFraction.value >= 0.5f) 1f else 0f
|
val snappedFraction = if (animatedFraction.value >= 0.5f) 1f else 0f
|
||||||
animatedFraction.animateTo(snappedFraction, progressAnimationSpec)
|
|
||||||
onCheckedChange(snappedFraction >= 0.5f)
|
onCheckedChange(snappedFraction >= 0.5f)
|
||||||
|
coroutineScope {
|
||||||
|
launch { progressAnimation.animateTo(0f, progressAnimationSpec) }
|
||||||
|
launch { animatedFraction.animateTo(snappedFraction, progressAnimationSpec) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) else Modifier)
|
) else Modifier)
|
||||||
@@ -175,12 +186,27 @@ fun StyledSwitch(
|
|||||||
color = Color.Black.copy(0.05f)
|
color = Color.Black.copy(0.05f)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
layer = {
|
layerBlock = {
|
||||||
val progress = progressAnimation.value
|
val progress = progressAnimation.value
|
||||||
val scale = lerp(1f, 2f, progress)
|
val scale = lerp(1f, 1.6f, progress)
|
||||||
scaleX = scale
|
scaleX = scale
|
||||||
scaleY = scale
|
scaleY = scale
|
||||||
},
|
},
|
||||||
|
onDrawBackdrop = { drawScope ->
|
||||||
|
drawIntoCanvas { canvas ->
|
||||||
|
canvas.save()
|
||||||
|
canvas.drawRect(0f, 0f, size.width, size.height, Paint().apply {
|
||||||
|
color = if (indpendent) {
|
||||||
|
if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7)
|
||||||
|
} else {
|
||||||
|
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
scale(0.75f) {
|
||||||
|
drawScope()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
onDrawSurface = {
|
onDrawSurface = {
|
||||||
val progress = progressAnimation.value.fastCoerceIn(0f, 1f)
|
val progress = progressAnimation.value.fastCoerceIn(0f, 1f)
|
||||||
|
|
||||||
@@ -224,12 +250,12 @@ fun StyledSwitch(
|
|||||||
@Composable
|
@Composable
|
||||||
fun StyledSwitchPreview() {
|
fun StyledSwitchPreview() {
|
||||||
val isDarkTheme = isSystemInDarkTheme()
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
val backgroundColor = if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7)
|
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFF2F2F7)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
.width(100.dp)
|
.width(100.dp)
|
||||||
.height(100.dp),
|
.height(400.dp),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
val checked = remember { mutableStateOf(true) }
|
val checked = remember { mutableStateOf(true) }
|
||||||
@@ -238,13 +264,14 @@ fun StyledSwitchPreview() {
|
|||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked.value = it
|
checked.value = it
|
||||||
},
|
},
|
||||||
enabled = true
|
enabled = true,
|
||||||
|
indpendent = false
|
||||||
)
|
)
|
||||||
LaunchedEffect(Unit) {
|
// LaunchedEffect(Unit) {
|
||||||
delay(1000)
|
// delay(1000)
|
||||||
checked.value = false
|
// checked.value = false
|
||||||
delay(1000)
|
// delay(1000)
|
||||||
checked.value = true
|
// checked.value = true
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ fun StyledToggle(
|
|||||||
sharedPreferenceKey: String? = null,
|
sharedPreferenceKey: String? = null,
|
||||||
sharedPreferences: SharedPreferences? = null,
|
sharedPreferences: SharedPreferences? = null,
|
||||||
independent: Boolean = true,
|
independent: Boolean = true,
|
||||||
|
enabled: Boolean = true,
|
||||||
onCheckedChange: ((Boolean) -> Unit)? = null,
|
onCheckedChange: ((Boolean) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val isDarkTheme = isSystemInDarkTheme()
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
@@ -82,7 +83,9 @@ fun StyledToggle(
|
|||||||
var checked by checkedState
|
var checked by checkedState
|
||||||
var backgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
var backgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
||||||
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
||||||
|
if (sharedPreferenceKey != null && sharedPreferences != null) {
|
||||||
|
checked = sharedPreferences.getBoolean(sharedPreferenceKey, checked)
|
||||||
|
}
|
||||||
fun cb() {
|
fun cb() {
|
||||||
if (sharedPreferences != null) {
|
if (sharedPreferences != null) {
|
||||||
if (sharedPreferenceKey == null) {
|
if (sharedPreferenceKey == null) {
|
||||||
@@ -101,15 +104,16 @@ fun StyledToggle(
|
|||||||
text = title,
|
text = title,
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f)
|
color = textColor.copy(alpha = 0.6f)
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 4.dp)
|
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 4.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(animatedBackgroundColor, RoundedCornerShape(14.dp))
|
.background(animatedBackgroundColor, RoundedCornerShape(28.dp))
|
||||||
|
.padding(4.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onPress = {
|
onPress = {
|
||||||
@@ -120,8 +124,10 @@ fun StyledToggle(
|
|||||||
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
},
|
},
|
||||||
onTap = {
|
onTap = {
|
||||||
checked = !checked
|
if (enabled) {
|
||||||
cb()
|
checked = !checked
|
||||||
|
cb()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -145,10 +151,14 @@ fun StyledToggle(
|
|||||||
)
|
)
|
||||||
StyledSwitch(
|
StyledSwitch(
|
||||||
checked = checked,
|
checked = checked,
|
||||||
|
enabled = enabled,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
if (enabled) {
|
||||||
cb()
|
checked = it
|
||||||
}
|
cb()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indpendent = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,7 +166,7 @@ fun StyledToggle(
|
|||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 8.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.background(if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7))
|
.background(if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7))
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
@@ -177,10 +187,10 @@ fun StyledToggle(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(
|
.background(
|
||||||
shape = RoundedCornerShape(14.dp),
|
shape = RoundedCornerShape(28.dp),
|
||||||
color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent
|
color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent
|
||||||
)
|
)
|
||||||
.padding(horizontal = 12.dp, vertical = 12.dp)
|
.padding(16.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onPress = {
|
onPress = {
|
||||||
@@ -194,8 +204,10 @@ fun StyledToggle(
|
|||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
) {
|
) {
|
||||||
checked = !checked
|
if (enabled) {
|
||||||
cb()
|
checked = !checked
|
||||||
|
cb()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
@@ -206,25 +218,35 @@ fun StyledToggle(
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = label,
|
text = label,
|
||||||
fontSize = 16.sp,
|
style = TextStyle(
|
||||||
color = textColor
|
fontSize = 16.sp,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
color = textColor
|
||||||
|
)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
Text(
|
Text(
|
||||||
text = description,
|
text = description,
|
||||||
fontSize = 12.sp,
|
style = TextStyle(
|
||||||
color = textColor.copy(0.6f),
|
fontSize = 12.sp,
|
||||||
lineHeight = 14.sp,
|
color = textColor.copy(0.6f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StyledSwitch(
|
StyledSwitch(
|
||||||
checked = checked,
|
checked = checked,
|
||||||
|
enabled = enabled,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
if (enabled) {
|
||||||
cb()
|
checked = it
|
||||||
}
|
cb()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indpendent = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,6 +259,7 @@ fun StyledToggle(
|
|||||||
description: String? = null,
|
description: String? = null,
|
||||||
controlCommandIdentifier: AACPManager.Companion.ControlCommandIdentifiers,
|
controlCommandIdentifier: AACPManager.Companion.ControlCommandIdentifiers,
|
||||||
independent: Boolean = true,
|
independent: Boolean = true,
|
||||||
|
enabled: Boolean = true,
|
||||||
sharedPreferenceKey: String? = null,
|
sharedPreferenceKey: String? = null,
|
||||||
sharedPreferences: SharedPreferences? = null,
|
sharedPreferences: SharedPreferences? = null,
|
||||||
onCheckedChange: ((Boolean) -> Unit)? = null,
|
onCheckedChange: ((Boolean) -> Unit)? = null,
|
||||||
@@ -291,15 +314,16 @@ fun StyledToggle(
|
|||||||
text = title,
|
text = title,
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f)
|
color = textColor.copy(alpha = 0.6f)
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 4.dp)
|
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 4.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(animatedBackgroundColor, RoundedCornerShape(14.dp))
|
.background(animatedBackgroundColor, RoundedCornerShape(28.dp))
|
||||||
|
.padding(4.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onPress = {
|
onPress = {
|
||||||
@@ -310,8 +334,10 @@ fun StyledToggle(
|
|||||||
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
},
|
},
|
||||||
onTap = {
|
onTap = {
|
||||||
checked = !checked
|
if (enabled) {
|
||||||
cb()
|
checked = !checked
|
||||||
|
cb()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -335,10 +361,14 @@ fun StyledToggle(
|
|||||||
)
|
)
|
||||||
StyledSwitch(
|
StyledSwitch(
|
||||||
checked = checked,
|
checked = checked,
|
||||||
|
enabled = enabled,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
if (enabled) {
|
||||||
cb()
|
checked = it
|
||||||
}
|
cb()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indpendent = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,7 +376,7 @@ fun StyledToggle(
|
|||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 8.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.background(if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7))
|
.background(if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7))
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
@@ -367,10 +397,10 @@ fun StyledToggle(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(
|
.background(
|
||||||
shape = RoundedCornerShape(14.dp),
|
shape = RoundedCornerShape(28.dp),
|
||||||
color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent
|
color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent
|
||||||
)
|
)
|
||||||
.padding(horizontal = 12.dp, vertical = 12.dp)
|
.padding(16.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onPress = {
|
onPress = {
|
||||||
@@ -384,8 +414,10 @@ fun StyledToggle(
|
|||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
) {
|
) {
|
||||||
checked = !checked
|
if (enabled) {
|
||||||
cb()
|
checked = !checked
|
||||||
|
cb()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
@@ -396,25 +428,35 @@ fun StyledToggle(
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = label,
|
text = label,
|
||||||
fontSize = 16.sp,
|
style = TextStyle(
|
||||||
color = textColor
|
fontSize = 16.sp,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
color = textColor
|
||||||
|
)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
Text(
|
Text(
|
||||||
text = description,
|
text = description,
|
||||||
fontSize = 12.sp,
|
style = TextStyle(
|
||||||
color = textColor.copy(0.6f),
|
fontSize = 12.sp,
|
||||||
lineHeight = 14.sp,
|
color = textColor.copy(0.6f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StyledSwitch(
|
StyledSwitch(
|
||||||
checked = checked,
|
checked = checked,
|
||||||
|
enabled = enabled,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
if (enabled) {
|
||||||
cb()
|
checked = it
|
||||||
}
|
cb()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indpendent = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -427,6 +469,7 @@ fun StyledToggle(
|
|||||||
description: String? = null,
|
description: String? = null,
|
||||||
attHandle: ATTHandles,
|
attHandle: ATTHandles,
|
||||||
independent: Boolean = true,
|
independent: Boolean = true,
|
||||||
|
enabled: Boolean = true,
|
||||||
sharedPreferenceKey: String? = null,
|
sharedPreferenceKey: String? = null,
|
||||||
sharedPreferences: SharedPreferences? = null,
|
sharedPreferences: SharedPreferences? = null,
|
||||||
onCheckedChange: ((Boolean) -> Unit)? = null,
|
onCheckedChange: ((Boolean) -> Unit)? = null,
|
||||||
@@ -509,15 +552,16 @@ fun StyledToggle(
|
|||||||
text = title,
|
text = title,
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f)
|
color = textColor.copy(alpha = 0.6f)
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 4.dp)
|
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 4.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(animatedBackgroundColor, RoundedCornerShape(14.dp))
|
.background(animatedBackgroundColor, RoundedCornerShape(28.dp))
|
||||||
|
.padding(4.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onPress = {
|
onPress = {
|
||||||
@@ -528,8 +572,10 @@ fun StyledToggle(
|
|||||||
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
},
|
},
|
||||||
onTap = {
|
onTap = {
|
||||||
checked = !checked
|
if (enabled) {
|
||||||
cb()
|
checked = !checked
|
||||||
|
cb()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -553,10 +599,14 @@ fun StyledToggle(
|
|||||||
)
|
)
|
||||||
StyledSwitch(
|
StyledSwitch(
|
||||||
checked = checked,
|
checked = checked,
|
||||||
|
enabled = enabled,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
if (enabled) {
|
||||||
cb()
|
checked = it
|
||||||
}
|
cb()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indpendent = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -564,7 +614,7 @@ fun StyledToggle(
|
|||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 8.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.background(if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7))
|
.background(if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7))
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
@@ -585,10 +635,10 @@ fun StyledToggle(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(
|
.background(
|
||||||
shape = RoundedCornerShape(14.dp),
|
shape = RoundedCornerShape(28.dp),
|
||||||
color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent
|
color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent
|
||||||
)
|
)
|
||||||
.padding(horizontal = 12.dp, vertical = 12.dp)
|
.padding(16.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onPress = {
|
onPress = {
|
||||||
@@ -602,8 +652,10 @@ fun StyledToggle(
|
|||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
) {
|
) {
|
||||||
checked = !checked
|
if (enabled) {
|
||||||
cb()
|
checked = !checked
|
||||||
|
cb()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
@@ -629,10 +681,14 @@ fun StyledToggle(
|
|||||||
}
|
}
|
||||||
StyledSwitch(
|
StyledSwitch(
|
||||||
checked = checked,
|
checked = checked,
|
||||||
|
enabled = enabled,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
checked = it
|
if (enabled) {
|
||||||
cb()
|
checked = it
|
||||||
}
|
cb()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indpendent = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,20 +40,16 @@ import androidx.compose.foundation.rememberScrollState
|
|||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
import androidx.compose.material3.CheckboxDefaults
|
import androidx.compose.material3.CheckboxDefaults
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.Slider
|
import androidx.compose.material3.Slider
|
||||||
import androidx.compose.material3.SliderDefaults
|
import androidx.compose.material3.SliderDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.MutableState
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableFloatStateOf
|
import androidx.compose.runtime.mutableFloatStateOf
|
||||||
import androidx.compose.runtime.mutableLongStateOf
|
import androidx.compose.runtime.mutableLongStateOf
|
||||||
@@ -79,6 +75,8 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.HazeState
|
import dev.chrisbanes.haze.HazeState
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
@@ -149,13 +147,16 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
|
|
||||||
StyledScaffold(
|
StyledScaffold(
|
||||||
title = stringResource(R.string.accessibility),
|
title = stringResource(R.string.accessibility),
|
||||||
navigationButton = {
|
navigationButton = {
|
||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { spacerHeight, hazeState ->
|
) { spacerHeight, hazeState ->
|
||||||
@@ -163,6 +164,7 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.hazeSource(hazeState)
|
.hazeSource(hazeState)
|
||||||
|
.layerBackdrop(backdrop)
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
@@ -370,7 +372,7 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
StyledToggle(
|
StyledToggle(
|
||||||
title = stringResource(R.string.noise_control).uppercase(),
|
title = stringResource(R.string.noise_control),
|
||||||
label = stringResource(R.string.noise_cancellation_single_airpod),
|
label = stringResource(R.string.noise_cancellation_single_airpod),
|
||||||
description = stringResource(R.string.noise_cancellation_single_airpod_description),
|
description = stringResource(R.string.noise_cancellation_single_airpod_description),
|
||||||
controlCommandIdentifier = AACPManager.Companion.ControlCommandIdentifiers.ONE_BUD_ANC_MODE,
|
controlCommandIdentifier = AACPManager.Companion.ControlCommandIdentifiers.ONE_BUD_ANC_MODE,
|
||||||
@@ -392,7 +394,7 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.tone_volume).uppercase(),
|
label = stringResource(R.string.tone_volume),
|
||||||
description = stringResource(R.string.tone_volume_description),
|
description = stringResource(R.string.tone_volume_description),
|
||||||
mutableFloatState = toneVolumeValue,
|
mutableFloatState = toneVolumeValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@@ -405,6 +407,12 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
|||||||
independent = true
|
independent = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
StyledToggle(
|
||||||
|
label = stringResource(R.string.volume_control),
|
||||||
|
description = stringResource(R.string.volume_control_description),
|
||||||
|
controlCommandIdentifier = AACPManager.Companion.ControlCommandIdentifiers.VOLUME_SWIPE_MODE,
|
||||||
|
)
|
||||||
|
|
||||||
DropdownMenuComponent(
|
DropdownMenuComponent(
|
||||||
label = stringResource(R.string.volume_swipe_speed),
|
label = stringResource(R.string.volume_swipe_speed),
|
||||||
description = stringResource(R.string.volume_swipe_speed_description),
|
description = stringResource(R.string.volume_swipe_speed_description),
|
||||||
@@ -425,10 +433,10 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
|||||||
|
|
||||||
if (!hearingAidEnabled.value&& isSdpOffsetAvailable.value) {
|
if (!hearingAidEnabled.value&& isSdpOffsetAvailable.value) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.apply_eq_to).uppercase(),
|
text = stringResource(R.string.apply_eq_to),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f),
|
color = textColor.copy(alpha = 0.6f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
@@ -437,12 +445,12 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
.padding(vertical = 0.dp)
|
.padding(vertical = 0.dp)
|
||||||
) {
|
) {
|
||||||
val darkModeLocal = isSystemInDarkTheme()
|
val darkModeLocal = isSystemInDarkTheme()
|
||||||
|
|
||||||
val phoneShape = RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp)
|
val phoneShape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp)
|
||||||
var phoneBackgroundColor by remember {
|
var phoneBackgroundColor by remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
if (darkModeLocal) Color(
|
if (darkModeLocal) Color(
|
||||||
@@ -500,11 +508,11 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888)
|
color = Color(0x40888888)
|
||||||
)
|
)
|
||||||
|
|
||||||
val mediaShape = RoundedCornerShape(bottomStart = 14.dp, bottomEnd = 14.dp)
|
val mediaShape = RoundedCornerShape(bottomStart = 28.dp, bottomEnd = 28.dp)
|
||||||
var mediaBackgroundColor by remember {
|
var mediaBackgroundColor by remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
if (darkModeLocal) Color(
|
if (darkModeLocal) Color(
|
||||||
@@ -565,7 +573,7 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
.padding(12.dp),
|
.padding(12.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
@@ -686,15 +694,18 @@ private fun DropdownMenuComponent(
|
|||||||
)
|
)
|
||||||
.background(
|
.background(
|
||||||
if (independent) (if (isSystemInDarkTheme()) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) else Color.Transparent,
|
if (independent) (if (isSystemInDarkTheme()) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) else Color.Transparent,
|
||||||
if (independent) RoundedCornerShape(14.dp) else RoundedCornerShape(0.dp)
|
if (independent) RoundedCornerShape(28.dp) else RoundedCornerShape(0.dp)
|
||||||
)
|
)
|
||||||
.clip(if (independent) RoundedCornerShape(14.dp) else RoundedCornerShape(0.dp))
|
then(
|
||||||
|
if (independent) Modifier.padding(horizontal = 4.dp) else Modifier
|
||||||
|
)
|
||||||
|
.clip(if (independent) RoundedCornerShape(28.dp) else RoundedCornerShape(0.dp))
|
||||||
){
|
){
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 12.dp, end = 12.dp)
|
.padding(start = 12.dp, end = 12.dp)
|
||||||
.height(55.dp)
|
.height(58.dp)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures { offset ->
|
detectTapGestures { offset ->
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
@@ -766,7 +777,7 @@ private fun DropdownMenuComponent(
|
|||||||
color = textColor.copy(alpha = 0.6f),
|
color = textColor.copy(alpha = 0.6f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(bottom = 2.dp)
|
modifier = Modifier.padding(16.dp, top = 0.dp, bottom = 2.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -780,14 +791,21 @@ private fun DropdownMenuComponent(
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = selectedOption,
|
text = selectedOption,
|
||||||
fontSize = 16.sp,
|
style = TextStyle(
|
||||||
color = textColor.copy(alpha = 0.8f)
|
fontSize = 16.sp,
|
||||||
|
color = textColor.copy(alpha = 0.8f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
Icon(
|
Text(
|
||||||
Icons.Default.KeyboardArrowDown,
|
text = "",
|
||||||
contentDescription = null,
|
style = TextStyle(
|
||||||
modifier = Modifier.size(18.dp),
|
fontSize = 16.sp,
|
||||||
tint = textColor.copy(alpha = 0.6f)
|
color = textColor.copy(alpha = 0.6f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 6.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,7 +834,7 @@ private fun DropdownMenuComponent(
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 8.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.background(if (isSystemInDarkTheme()) Color(0xFF000000) else Color(0xFFF2F2F7))
|
.background(if (isSystemInDarkTheme()) Color(0xFF000000) else Color(0xFFF2F2F7))
|
||||||
){
|
){
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -94,6 +96,7 @@ fun AdaptiveStrengthScreen(navController: NavController) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
|
|
||||||
StyledScaffold(
|
StyledScaffold(
|
||||||
title = stringResource(R.string.customize_adaptive_audio),
|
title = stringResource(R.string.customize_adaptive_audio),
|
||||||
@@ -101,19 +104,21 @@ fun AdaptiveStrengthScreen(navController: NavController) {
|
|||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { spacerHeight ->
|
) { spacerHeight ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
.layerBackdrop(backdrop)
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
Spacer(modifier = Modifier.height(spacerHeight))
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.customize_adaptive_audio).uppercase(),
|
label = stringResource(R.string.customize_adaptive_audio),
|
||||||
mutableFloatState = sliderValue,
|
mutableFloatState = sliderValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
sliderValue.floatValue = it
|
sliderValue.floatValue = it
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import com.kyant.backdrop.drawBackdrop
|
import com.kyant.backdrop.drawBackdrop
|
||||||
import com.kyant.backdrop.highlight.Highlight
|
import com.kyant.backdrop.highlight.Highlight
|
||||||
@@ -80,7 +81,6 @@ import me.kavishdevar.librepods.composables.BatteryView
|
|||||||
import me.kavishdevar.librepods.composables.CallControlSettings
|
import me.kavishdevar.librepods.composables.CallControlSettings
|
||||||
import me.kavishdevar.librepods.composables.ConnectionSettings
|
import me.kavishdevar.librepods.composables.ConnectionSettings
|
||||||
import me.kavishdevar.librepods.composables.MicrophoneSettings
|
import me.kavishdevar.librepods.composables.MicrophoneSettings
|
||||||
import me.kavishdevar.librepods.composables.NameField
|
|
||||||
import me.kavishdevar.librepods.composables.NavigationButton
|
import me.kavishdevar.librepods.composables.NavigationButton
|
||||||
import me.kavishdevar.librepods.composables.NoiseControlSettings
|
import me.kavishdevar.librepods.composables.NoiseControlSettings
|
||||||
import me.kavishdevar.librepods.composables.PressAndHoldSettings
|
import me.kavishdevar.librepods.composables.PressAndHoldSettings
|
||||||
@@ -199,13 +199,15 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val darkMode = isSystemInDarkTheme()
|
val darkMode = isSystemInDarkTheme()
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
StyledScaffold(
|
StyledScaffold(
|
||||||
title = deviceName.text,
|
title = deviceName.text,
|
||||||
actionButtons = listOf {
|
actionButtons = listOf {
|
||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.navigate("app_settings") },
|
onClick = { navController.navigate("app_settings") },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = darkMode
|
darkMode = darkMode,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
snackbarHostState = snackbarHostState
|
snackbarHostState = snackbarHostState
|
||||||
@@ -216,6 +218,7 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.hazeSource(hazeState)
|
.hazeSource(hazeState)
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
|
.layerBackdrop(backdrop)
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
Spacer(modifier = Modifier.height(spacerHeight))
|
||||||
@@ -249,28 +252,28 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
|||||||
|
|
||||||
// Only show name field when not in BLE-only mode
|
// Only show name field when not in BLE-only mode
|
||||||
if (!bleOnlyMode) {
|
if (!bleOnlyMode) {
|
||||||
NameField(
|
NavigationButton(
|
||||||
|
to = "rename",
|
||||||
name = stringResource(R.string.name),
|
name = stringResource(R.string.name),
|
||||||
value = deviceName.text,
|
currentState = deviceName.text,
|
||||||
navController = navController
|
navController = navController,
|
||||||
|
independent = true
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
if (!bleOnlyMode) {
|
|
||||||
Spacer(modifier = Modifier.height(32.dp))
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
NavigationButton(to = "hearing_aid", stringResource(R.string.hearing_aid), navController)
|
NavigationButton(to = "hearing_aid", stringResource(R.string.hearing_aid), navController)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
NoiseControlSettings(service = service)
|
NoiseControlSettings(service = service)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
PressAndHoldSettings(navController = navController)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
CallControlSettings(hazeState = hazeState)
|
CallControlSettings(hazeState = hazeState)
|
||||||
|
|
||||||
// camera control goes here, airpods side is done, i just need to figure out how to listen to app open/close events
|
// camera control goes here, airpods side is done, i just need to figure out how to listen to app open/close events
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
PressAndHoldSettings(navController = navController)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
AudioSettings(navController = navController)
|
AudioSettings(navController = navController)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -40,14 +40,11 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
|
||||||
import androidx.compose.material.icons.filled.Send
|
import androidx.compose.material.icons.filled.Send
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
@@ -78,6 +75,8 @@ import androidx.compose.ui.text.input.TextFieldValue
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -325,14 +324,15 @@ fun DebugScreen(navController: NavController) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val isDarkTheme = isSystemInDarkTheme()
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
StyledScaffold(
|
StyledScaffold(
|
||||||
title = "Debug",
|
title = "Debug",
|
||||||
navigationButton = {
|
navigationButton = {
|
||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
actionButtons = listOf(
|
actionButtons = listOf(
|
||||||
@@ -344,6 +344,7 @@ fun DebugScreen(navController: NavController) {
|
|||||||
},
|
},
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme,
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -353,6 +354,7 @@ fun DebugScreen(navController: NavController) {
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.hazeSource(hazeState)
|
.hazeSource(hazeState)
|
||||||
.navigationBarsPadding()
|
.navigationBarsPadding()
|
||||||
|
.layerBackdrop(backdrop)
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
Spacer(modifier = Modifier.height(spacerHeight))
|
||||||
@@ -391,11 +393,13 @@ fun DebugScreen(navController: NavController) {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Icon(
|
Text(
|
||||||
imageVector = if (isSent) Icons.AutoMirrored.Filled.KeyboardArrowLeft else Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
text = if (isSent) "" else "",
|
||||||
contentDescription = null,
|
style = TextStyle(
|
||||||
tint = if (isSent) Color.Green else Color.Red,
|
fontSize = 16.sp,
|
||||||
modifier = Modifier.size(24.dp)
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
color = if (isSent) Color(0xFF4CD964) else Color(0xFFFF3B30)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
Column {
|
Column {
|
||||||
|
|||||||
@@ -42,10 +42,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.ButtonDefaults
|
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
@@ -87,12 +84,15 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.kavishdevar.librepods.R
|
import me.kavishdevar.librepods.R
|
||||||
|
import me.kavishdevar.librepods.composables.StyledButton
|
||||||
import me.kavishdevar.librepods.composables.StyledIconButton
|
import me.kavishdevar.librepods.composables.StyledIconButton
|
||||||
import me.kavishdevar.librepods.composables.StyledScaffold
|
import me.kavishdevar.librepods.composables.StyledScaffold
|
||||||
import me.kavishdevar.librepods.composables.StyledToggle
|
import me.kavishdevar.librepods.composables.StyledToggle
|
||||||
@@ -116,18 +116,19 @@ fun HeadTrackingScreen(navController: NavController) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val isDarkTheme = isSystemInDarkTheme()
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
val textColor = if (isDarkTheme) Color.White else Color.Black
|
val textColor = if (isDarkTheme) Color.White else Color.Black
|
||||||
|
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
StyledScaffold (
|
StyledScaffold (
|
||||||
title = stringResource(R.string.head_tracking),
|
title = stringResource(R.string.head_tracking),
|
||||||
navigationButton = {
|
navigationButton = {
|
||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
actionButtons = listOf(
|
actionButtons = listOf(
|
||||||
@@ -144,72 +145,95 @@ fun HeadTrackingScreen(navController: NavController) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon = if (isActive) "" else "",
|
icon = if (isActive) "" else "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
) { spacerHeight, hazeState ->
|
) { spacerHeight, hazeState ->
|
||||||
Column (
|
val backdrop = rememberLayerBackdrop()
|
||||||
|
val sharedPreferences = LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
var gestureText by remember { mutableStateOf("") }
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
var lastClickTime by remember { mutableLongStateOf(0L) }
|
||||||
|
var shouldExplode by remember { mutableStateOf(false) }
|
||||||
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.layerBackdrop(backdrop)
|
||||||
.padding(top = 8.dp)
|
.fillMaxWidth(),
|
||||||
.padding(horizontal = 16.dp)
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
.verticalScroll(scrollState)
|
|
||||||
.hazeSource(state = hazeState)
|
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
Column (
|
||||||
val sharedPreferences =
|
modifier = Modifier
|
||||||
LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp)
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
.verticalScroll(scrollState)
|
||||||
|
.hazeSource(state = hazeState)
|
||||||
|
.layerBackdrop(
|
||||||
|
backdrop = backdrop
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.height(spacerHeight))
|
||||||
|
StyledToggle(
|
||||||
|
label = "Head Gestures",
|
||||||
|
sharedPreferences = sharedPreferences,
|
||||||
|
sharedPreferenceKey = "head_gestures",
|
||||||
|
)
|
||||||
|
|
||||||
var gestureText by remember { mutableStateOf("") }
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
val coroutineScope = rememberCoroutineScope()
|
Text(
|
||||||
|
stringResource(R.string.head_gestures_details),
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
color = textColor.copy(0.6f)
|
||||||
|
),
|
||||||
|
modifier = Modifier.padding(start = 4.dp)
|
||||||
|
)
|
||||||
|
|
||||||
StyledToggle(
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
label = "Head Gestures",
|
Text(
|
||||||
sharedPreferences = sharedPreferences,
|
"Head Orientation",
|
||||||
sharedPreferenceKey = "head_gestures",
|
style = TextStyle(
|
||||||
)
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
Text(
|
color = textColor
|
||||||
stringResource(R.string.head_gestures_details),
|
),
|
||||||
style = TextStyle(
|
modifier = Modifier.padding(start = 4.dp, bottom = 8.dp, top = 8.dp)
|
||||||
fontSize = 14.sp,
|
)
|
||||||
fontWeight = FontWeight.Normal,
|
HeadVisualization()
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
|
||||||
color = textColor.copy(0.6f)
|
|
||||||
),
|
|
||||||
modifier = Modifier.padding(start = 4.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Text(
|
Text(
|
||||||
"Head Orientation",
|
"Velocity",
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 18.sp,
|
fontSize = 18.sp,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
color = textColor
|
color = textColor
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(start = 4.dp, bottom = 8.dp, top = 8.dp)
|
modifier = Modifier.padding(start = 4.dp, bottom = 8.dp, top = 8.dp)
|
||||||
)
|
)
|
||||||
HeadVisualization()
|
AccelerationPlot()
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Text(
|
|
||||||
"Velocity",
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 18.sp,
|
|
||||||
fontWeight = FontWeight.Medium,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
|
||||||
color = textColor
|
|
||||||
),
|
|
||||||
modifier = Modifier.padding(start = 4.dp, bottom = 8.dp, top = 8.dp)
|
|
||||||
)
|
|
||||||
AccelerationPlot()
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
LaunchedEffect(gestureText) {
|
||||||
Button (
|
if (gestureText.isNotEmpty()) {
|
||||||
|
lastClickTime = System.currentTimeMillis()
|
||||||
|
delay(3000)
|
||||||
|
if (System.currentTimeMillis() - lastClickTime >= 3000) {
|
||||||
|
shouldExplode = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StyledButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
gestureText = "Shake your head or nod!"
|
gestureText = "Shake your head or nod!"
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
@@ -217,13 +241,9 @@ fun HeadTrackingScreen(navController: NavController) {
|
|||||||
gestureText = if (accepted) "\"Yes\" gesture detected." else "\"No\" gesture detected."
|
gestureText = if (accepted) "\"Yes\" gesture detected." else "\"No\" gesture detected."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
backdrop = backdrop,
|
||||||
.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth(0.75f),
|
||||||
.height(55.dp),
|
maxScale = 0.05f
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
containerColor = backgroundColor
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(8.dp)
|
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
"Test Head Gestures",
|
"Test Head Gestures",
|
||||||
@@ -235,19 +255,6 @@ fun HeadTrackingScreen(navController: NavController) {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
var lastClickTime by remember { mutableLongStateOf(0L) }
|
|
||||||
var shouldExplode by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
LaunchedEffect(gestureText) {
|
|
||||||
if (gestureText.isNotEmpty()) {
|
|
||||||
lastClickTime = System.currentTimeMillis()
|
|
||||||
delay(3000)
|
|
||||||
if (System.currentTimeMillis() - lastClickTime >= 3000) {
|
|
||||||
shouldExplode = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
modifier = Modifier.padding(top = 12.dp, bottom = 24.dp)
|
modifier = Modifier.padding(top = 12.dp, bottom = 24.dp)
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.HazeState
|
import dev.chrisbanes.haze.HazeState
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
@@ -77,14 +79,15 @@ fun HearingAidAdjustmentsScreen(@Suppress("unused") navController: NavController
|
|||||||
val attManager = ServiceManager.getService()?.attManager ?: throw IllegalStateException("ATTManager not available")
|
val attManager = ServiceManager.getService()?.attManager ?: throw IllegalStateException("ATTManager not available")
|
||||||
|
|
||||||
val aacpManager = remember { ServiceManager.getService()?.aacpManager }
|
val aacpManager = remember { ServiceManager.getService()?.aacpManager }
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
StyledScaffold(
|
StyledScaffold(
|
||||||
title = stringResource(R.string.adjustments),
|
title = stringResource(R.string.adjustments),
|
||||||
navigationButton = {
|
navigationButton = {
|
||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { spacerHeight ->
|
) { spacerHeight ->
|
||||||
@@ -92,6 +95,7 @@ fun HearingAidAdjustmentsScreen(@Suppress("unused") navController: NavController
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.hazeSource(hazeState)
|
.hazeSource(hazeState)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
.layerBackdrop(backdrop)
|
||||||
.verticalScroll(verticalScrollState)
|
.verticalScroll(verticalScrollState)
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
@@ -282,7 +286,7 @@ fun HearingAidAdjustmentsScreen(@Suppress("unused") navController: NavController
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.amplification).uppercase(),
|
label = stringResource(R.string.amplification),
|
||||||
valueRange = -1f..1f,
|
valueRange = -1f..1f,
|
||||||
mutableFloatState = amplificationSliderValue,
|
mutableFloatState = amplificationSliderValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@@ -301,20 +305,20 @@ fun HearingAidAdjustmentsScreen(@Suppress("unused") navController: NavController
|
|||||||
)
|
)
|
||||||
|
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.balance).uppercase(),
|
label = stringResource(R.string.balance),
|
||||||
valueRange = -1f..1f,
|
valueRange = -1f..1f,
|
||||||
mutableFloatState = balanceSliderValue,
|
mutableFloatState = balanceSliderValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
balanceSliderValue.floatValue = it
|
balanceSliderValue.floatValue = it
|
||||||
},
|
},
|
||||||
snapPoints = listOf(0f),
|
snapPoints = listOf(-1f, 0f, 1f),
|
||||||
startLabel = stringResource(R.string.left),
|
startLabel = stringResource(R.string.left),
|
||||||
endLabel = stringResource(R.string.right),
|
endLabel = stringResource(R.string.right),
|
||||||
independent = true,
|
independent = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.tone).uppercase(),
|
label = stringResource(R.string.tone),
|
||||||
valueRange = -1f..1f,
|
valueRange = -1f..1f,
|
||||||
mutableFloatState = toneSliderValue,
|
mutableFloatState = toneSliderValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@@ -326,7 +330,7 @@ fun HearingAidAdjustmentsScreen(@Suppress("unused") navController: NavController
|
|||||||
)
|
)
|
||||||
|
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.ambient_noise_reduction).uppercase(),
|
label = stringResource(R.string.ambient_noise_reduction),
|
||||||
valueRange = 0f..1f,
|
valueRange = 0f..1f,
|
||||||
mutableFloatState = ambientNoiseReductionSliderValue,
|
mutableFloatState = ambientNoiseReductionSliderValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
|
|||||||
@@ -20,15 +20,10 @@ package me.kavishdevar.librepods.screens
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.animation.animateColorAsState
|
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@@ -37,25 +32,18 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.Font
|
import androidx.compose.ui.text.font.Font
|
||||||
@@ -74,9 +62,9 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.kavishdevar.librepods.R
|
import me.kavishdevar.librepods.R
|
||||||
import me.kavishdevar.librepods.composables.ConfirmationDialog
|
import me.kavishdevar.librepods.composables.ConfirmationDialog
|
||||||
|
import me.kavishdevar.librepods.composables.NavigationButton
|
||||||
import me.kavishdevar.librepods.composables.StyledIconButton
|
import me.kavishdevar.librepods.composables.StyledIconButton
|
||||||
import me.kavishdevar.librepods.composables.StyledScaffold
|
import me.kavishdevar.librepods.composables.StyledScaffold
|
||||||
import me.kavishdevar.librepods.composables.StyledSwitch
|
|
||||||
import me.kavishdevar.librepods.composables.StyledToggle
|
import me.kavishdevar.librepods.composables.StyledToggle
|
||||||
import me.kavishdevar.librepods.services.ServiceManager
|
import me.kavishdevar.librepods.services.ServiceManager
|
||||||
import me.kavishdevar.librepods.utils.AACPManager
|
import me.kavishdevar.librepods.utils.AACPManager
|
||||||
@@ -117,7 +105,8 @@ fun HearingAidScreen(navController: NavController) {
|
|||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
actionButtons = emptyList(),
|
actionButtons = emptyList(),
|
||||||
@@ -129,7 +118,7 @@ fun HearingAidScreen(navController: NavController) {
|
|||||||
.hazeSource(hazeState)
|
.hazeSource(hazeState)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(verticalScrollState)
|
.verticalScroll(verticalScrollState)
|
||||||
.padding(16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
Spacer(modifier = Modifier.height(spacerHeight))
|
||||||
@@ -175,22 +164,22 @@ fun HearingAidScreen(navController: NavController) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onAdjustPhoneChange(value: Boolean) {
|
fun onAdjustPhoneChange(value: Boolean) {
|
||||||
adjustPhoneEnabled.value = value
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onAdjustMediaChange(value: Boolean) {
|
fun onAdjustMediaChange(value: Boolean) {
|
||||||
adjustMediaEnabled.value = value
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.hearing_aid).uppercase(),
|
text = stringResource(R.string.hearing_aid),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f),
|
color = textColor.copy(alpha = 0.6f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
modifier = Modifier.padding(16.dp, bottom = 2.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
@@ -198,9 +187,9 @@ fun HearingAidScreen(navController: NavController) {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
.clip(
|
.clip(
|
||||||
RoundedCornerShape(14.dp)
|
RoundedCornerShape(28.dp)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
StyledToggle(
|
StyledToggle(
|
||||||
@@ -209,31 +198,17 @@ fun HearingAidScreen(navController: NavController) {
|
|||||||
independent = false
|
independent = false
|
||||||
)
|
)
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp, end = 0.dp)
|
.padding(horizontal = 12.dp)
|
||||||
|
)
|
||||||
|
NavigationButton(
|
||||||
|
to = "hearing_aid_adjustments",
|
||||||
|
name = stringResource(R.string.adjustments),
|
||||||
|
navController,
|
||||||
|
independent = false
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.clickable { navController.navigate("hearing_aid_adjustments") }
|
|
||||||
.padding(12.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.adjustments),
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
|
||||||
contentDescription = null,
|
|
||||||
tint = textColor
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.hearing_aid_description),
|
text = stringResource(R.string.hearing_aid_description),
|
||||||
@@ -243,12 +218,12 @@ fun HearingAidScreen(navController: NavController) {
|
|||||||
color = (if (isSystemInDarkTheme()) Color.White else Color.Black).copy(alpha = 0.6f),
|
color = (if (isSystemInDarkTheme()) Color.White else Color.Black).copy(alpha = 0.6f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(horizontal = 8.dp)
|
modifier = Modifier.padding(horizontal = 16.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
StyledToggle(
|
StyledToggle(
|
||||||
title = stringResource(R.string.media_assist).uppercase(),
|
title = stringResource(R.string.media_assist),
|
||||||
label = stringResource(R.string.media_assist),
|
label = stringResource(R.string.media_assist),
|
||||||
checkedState = mediaAssistEnabled,
|
checkedState = mediaAssistEnabled,
|
||||||
independent = true,
|
independent = true,
|
||||||
@@ -260,99 +235,27 @@ fun HearingAidScreen(navController: NavController) {
|
|||||||
Column (
|
Column (
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
) {
|
) {
|
||||||
val isDarkThemeLocal = isSystemInDarkTheme()
|
StyledToggle(
|
||||||
var backgroundColorAdjustMedia by remember { mutableStateOf(if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
label = stringResource(R.string.adjust_media),
|
||||||
val animatedBackgroundColorAdjustMedia by animateColorAsState(targetValue = backgroundColorAdjustMedia, animationSpec = tween(durationMillis = 500))
|
checkedState = adjustMediaEnabled,
|
||||||
Row(
|
onCheckedChange = { onAdjustMediaChange(it) },
|
||||||
modifier = Modifier
|
independent = false
|
||||||
.fillMaxWidth()
|
)
|
||||||
.padding(12.dp)
|
|
||||||
.pointerInput(Unit) {
|
|
||||||
detectTapGestures(
|
|
||||||
onPress = {
|
|
||||||
backgroundColorAdjustMedia = if (isDarkThemeLocal) Color(0x40888888) else Color(0x40D9D9D9)
|
|
||||||
tryAwaitRelease()
|
|
||||||
backgroundColorAdjustMedia = if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
|
||||||
},
|
|
||||||
onTap = {
|
|
||||||
onAdjustMediaChange(!adjustMediaEnabled.value)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.background(
|
|
||||||
animatedBackgroundColorAdjustMedia,
|
|
||||||
RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp)
|
|
||||||
),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.adjust_media),
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
)
|
|
||||||
StyledSwitch(
|
|
||||||
checked = adjustMediaEnabled.value,
|
|
||||||
onCheckedChange = {
|
|
||||||
onAdjustMediaChange(it)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 12.dp, end = 0.dp)
|
.padding(horizontal = 12.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
var backgroundColorAdjustPhone by remember { mutableStateOf(if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
StyledToggle(
|
||||||
val animatedBackgroundColorAdjustPhone by animateColorAsState(targetValue = backgroundColorAdjustPhone, animationSpec = tween(durationMillis = 500))
|
label = stringResource(R.string.adjust_calls),
|
||||||
Row(
|
checkedState = adjustPhoneEnabled,
|
||||||
modifier = Modifier
|
onCheckedChange = { onAdjustPhoneChange(it) },
|
||||||
.fillMaxWidth()
|
independent = false
|
||||||
.padding(12.dp)
|
)
|
||||||
.pointerInput(Unit) {
|
|
||||||
detectTapGestures(
|
|
||||||
onPress = {
|
|
||||||
backgroundColorAdjustPhone = if (isDarkThemeLocal) Color(0x40888888) else Color(0x40D9D9D9)
|
|
||||||
tryAwaitRelease()
|
|
||||||
backgroundColorAdjustPhone = if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
|
||||||
},
|
|
||||||
onTap = {
|
|
||||||
onAdjustPhoneChange(!adjustPhoneEnabled.value)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.background(
|
|
||||||
animatedBackgroundColorAdjustPhone,
|
|
||||||
RoundedCornerShape(bottomStart = 14.dp, bottomEnd = 14.dp)
|
|
||||||
),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.adjust_calls),
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
color = textColor
|
|
||||||
)
|
|
||||||
)
|
|
||||||
StyledSwitch(
|
|
||||||
checked = adjustPhoneEnabled.value,
|
|
||||||
onCheckedChange = {
|
|
||||||
onAdjustPhoneChange(it)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -151,6 +153,7 @@ fun Onboarding(navController: NavController, activityContext: Context) {
|
|||||||
isComplete = true
|
isComplete = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
StyledScaffold(
|
StyledScaffold(
|
||||||
title = "Setting Up",
|
title = "Setting Up",
|
||||||
actionButtons = listOf(
|
actionButtons = listOf(
|
||||||
@@ -160,7 +163,8 @@ fun Onboarding(navController: NavController, activityContext: Context) {
|
|||||||
showSkipDialog = true
|
showSkipDialog = true
|
||||||
},
|
},
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -168,6 +172,7 @@ fun Onboarding(navController: NavController, activityContext: Context) {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
.layerBackdrop(backdrop)
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ package me.kavishdevar.librepods.screens
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.animation.animateColorAsState
|
import androidx.compose.animation.animateColorAsState
|
||||||
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
@@ -37,8 +38,6 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.wrapContentWidth
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Checkbox
|
|
||||||
import androidx.compose.material3.CheckboxDefaults
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@@ -50,11 +49,11 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.scale
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.Font
|
import androidx.compose.ui.text.font.Font
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
@@ -63,6 +62,8 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import me.kavishdevar.librepods.R
|
import me.kavishdevar.librepods.R
|
||||||
import me.kavishdevar.librepods.composables.StyledIconButton
|
import me.kavishdevar.librepods.composables.StyledIconButton
|
||||||
@@ -76,20 +77,20 @@ import kotlin.io.encoding.ExperimentalEncodingApi
|
|||||||
@Composable
|
@Composable
|
||||||
fun RightDivider() {
|
fun RightDivider() {
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 72.dp)
|
.padding(start = 72.dp, end = 20.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RightDividerNoIcon() {
|
fun RightDividerNoIcon() {
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 1.5.dp,
|
thickness = 1.dp,
|
||||||
color = Color(0x40888888),
|
color = Color(0x40888888),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 20.dp)
|
.padding(start = 20.dp, end = 20.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,19 +118,22 @@ fun LongPress(navController: NavController, name: String) {
|
|||||||
val longPressActionPref = sharedPreferences.getString(prefKey, StemAction.CYCLE_NOISE_CONTROL_MODES.name)
|
val longPressActionPref = sharedPreferences.getString(prefKey, StemAction.CYCLE_NOISE_CONTROL_MODES.name)
|
||||||
Log.d("PressAndHoldSettingsScreen", "Long press action preference ($prefKey): $longPressActionPref")
|
Log.d("PressAndHoldSettingsScreen", "Long press action preference ($prefKey): $longPressActionPref")
|
||||||
var longPressAction by remember { mutableStateOf(StemAction.valueOf(longPressActionPref ?: StemAction.CYCLE_NOISE_CONTROL_MODES.name)) }
|
var longPressAction by remember { mutableStateOf(StemAction.valueOf(longPressActionPref ?: StemAction.CYCLE_NOISE_CONTROL_MODES.name)) }
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
StyledScaffold(
|
StyledScaffold(
|
||||||
title = name,
|
title = name,
|
||||||
navigationButton = {
|
navigationButton = {
|
||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { spacerHeight ->
|
) { spacerHeight ->
|
||||||
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
Column (
|
Column (
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.layerBackdrop(backdrop)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(top = 8.dp)
|
.padding(top = 8.dp)
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
@@ -138,11 +142,11 @@ fun LongPress(navController: NavController, name: String) {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp)),
|
.background(backgroundColor, RoundedCornerShape(28.dp)),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
LongPressActionElement(
|
LongPressActionElement(
|
||||||
name = "Noise Control",
|
name = stringResource(R.string.noise_control),
|
||||||
selected = longPressAction == StemAction.CYCLE_NOISE_CONTROL_MODES,
|
selected = longPressAction == StemAction.CYCLE_NOISE_CONTROL_MODES,
|
||||||
onClick = {
|
onClick = {
|
||||||
longPressAction = StemAction.CYCLE_NOISE_CONTROL_MODES
|
longPressAction = StemAction.CYCLE_NOISE_CONTROL_MODES
|
||||||
@@ -153,7 +157,7 @@ fun LongPress(navController: NavController, name: String) {
|
|||||||
)
|
)
|
||||||
RightDividerNoIcon()
|
RightDividerNoIcon()
|
||||||
LongPressActionElement(
|
LongPressActionElement(
|
||||||
name = "Digital Assistant",
|
name = stringResource(R.string.digital_assistant),
|
||||||
selected = longPressAction == StemAction.DIGITAL_ASSISTANT,
|
selected = longPressAction == StemAction.DIGITAL_ASSISTANT,
|
||||||
onClick = {
|
onClick = {
|
||||||
longPressAction = StemAction.DIGITAL_ASSISTANT
|
longPressAction = StemAction.DIGITAL_ASSISTANT
|
||||||
@@ -165,23 +169,25 @@ fun LongPress(navController: NavController, name: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (longPressAction == StemAction.CYCLE_NOISE_CONTROL_MODES) {
|
if (longPressAction == StemAction.CYCLE_NOISE_CONTROL_MODES) {
|
||||||
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "NOISE CONTROL",
|
text = stringResource(R.string.noise_control),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f),
|
color = textColor.copy(alpha = 0.6f),
|
||||||
),
|
),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(top = 32.dp, bottom = 4.dp)
|
.padding(horizontal = 18.dp)
|
||||||
.padding(horizontal = 8.dp)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp)),
|
.background(backgroundColor, RoundedCornerShape(28.dp)),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
val offListeningModeValue = ServiceManager.getService()!!.aacpManager.controlCommandStatusList.find {
|
val offListeningModeValue = ServiceManager.getService()!!.aacpManager.controlCommandStatusList.find {
|
||||||
@@ -189,28 +195,28 @@ fun LongPress(navController: NavController, name: String) {
|
|||||||
}?.value?.takeIf { it.isNotEmpty() }?.get(0)
|
}?.value?.takeIf { it.isNotEmpty() }?.get(0)
|
||||||
val offListeningMode = offListeningModeValue == 1.toByte()
|
val offListeningMode = offListeningModeValue == 1.toByte()
|
||||||
ListeningModeElement(
|
ListeningModeElement(
|
||||||
name = "Off",
|
name = stringResource(R.string.off),
|
||||||
enabled = offListeningMode,
|
enabled = offListeningMode,
|
||||||
resourceId = R.drawable.noise_cancellation,
|
resourceId = R.drawable.noise_cancellation,
|
||||||
isFirst = true)
|
isFirst = true)
|
||||||
if (offListeningMode) RightDivider()
|
if (offListeningMode) RightDivider()
|
||||||
ListeningModeElement(
|
ListeningModeElement(
|
||||||
name = "Transparency",
|
name = stringResource(R.string.transparency),
|
||||||
resourceId = R.drawable.transparency,
|
resourceId = R.drawable.transparency,
|
||||||
isFirst = !offListeningMode)
|
isFirst = !offListeningMode)
|
||||||
RightDivider()
|
RightDivider()
|
||||||
ListeningModeElement(
|
ListeningModeElement(
|
||||||
name = "Adaptive",
|
name = stringResource(R.string.adaptive),
|
||||||
resourceId = R.drawable.adaptive)
|
resourceId = R.drawable.adaptive)
|
||||||
RightDivider()
|
RightDivider()
|
||||||
ListeningModeElement(
|
ListeningModeElement(
|
||||||
name = "Noise Cancellation",
|
name = stringResource(R.string.noise_cancellation),
|
||||||
resourceId = R.drawable.noise_cancellation,
|
resourceId = R.drawable.noise_cancellation,
|
||||||
isLast = true)
|
isLast = true)
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "Press and hold the stem to cycle between the selected noise control modes.",
|
text = stringResource(R.string.press_and_hold_noise_control_description),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 12.sp,
|
fontSize = 12.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Light,
|
||||||
@@ -218,7 +224,7 @@ fun LongPress(navController: NavController, name: String) {
|
|||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 8.dp)
|
.padding(horizontal = 18.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,8 +335,8 @@ fun ListeningModeElement(name: String, enabled: Boolean = true, resourceId: Int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
val shape = when {
|
val shape = when {
|
||||||
isFirst -> RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp)
|
isFirst -> RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp)
|
||||||
isLast -> RoundedCornerShape(bottomStart = 14.dp, bottomEnd = 14.dp)
|
isLast -> RoundedCornerShape(bottomStart = 28.dp, bottomEnd = 28.dp)
|
||||||
else -> RoundedCornerShape(0.dp)
|
else -> RoundedCornerShape(0.dp)
|
||||||
}
|
}
|
||||||
var backgroundColor by remember { mutableStateOf(if (darkMode) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
var backgroundColor by remember { mutableStateOf(if (darkMode) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
||||||
@@ -352,7 +358,7 @@ fun ListeningModeElement(name: String, enabled: Boolean = true, resourceId: Int,
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.padding(horizontal = 16.dp, vertical = 0.dp),
|
.padding(horizontal = 16.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
@@ -384,24 +390,19 @@ fun ListeningModeElement(name: String, enabled: Boolean = true, resourceId: Int,
|
|||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Checkbox(
|
|
||||||
checked = checked.value,
|
val floatAnimateState by animateFloatAsState(
|
||||||
onCheckedChange = { valueChanged() },
|
targetValue = if (checked.value) 1f else 0f,
|
||||||
colors = CheckboxDefaults.colors().copy(
|
animationSpec = tween(durationMillis = 300)
|
||||||
checkedCheckmarkColor = Color(0xFF007AFF),
|
)
|
||||||
uncheckedCheckmarkColor = Color.Transparent,
|
Text(
|
||||||
checkedBoxColor = Color.Transparent,
|
text = "",
|
||||||
uncheckedBoxColor = Color.Transparent,
|
style = TextStyle(
|
||||||
checkedBorderColor = Color.Transparent,
|
fontSize = 20.sp,
|
||||||
uncheckedBorderColor = Color.Transparent,
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
disabledBorderColor = Color.Transparent,
|
color = Color(0xFF007AFF).copy(alpha = floatAnimateState),
|
||||||
disabledCheckedBoxColor = Color.Transparent,
|
|
||||||
disabledUncheckedBoxColor = Color.Transparent,
|
|
||||||
disabledUncheckedBorderColor = Color.Transparent
|
|
||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier.padding(end = 4.dp)
|
||||||
.height(24.dp)
|
|
||||||
.scale(1.5f),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -417,15 +418,15 @@ fun LongPressActionElement(
|
|||||||
) {
|
) {
|
||||||
val darkMode = isSystemInDarkTheme()
|
val darkMode = isSystemInDarkTheme()
|
||||||
val shape = when {
|
val shape = when {
|
||||||
isFirst -> RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp)
|
isFirst -> RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp)
|
||||||
isLast -> RoundedCornerShape(bottomStart = 14.dp, bottomEnd = 14.dp)
|
isLast -> RoundedCornerShape(bottomStart = 28.dp, bottomEnd = 28.dp)
|
||||||
else -> RoundedCornerShape(0.dp)
|
else -> RoundedCornerShape(0.dp)
|
||||||
}
|
}
|
||||||
var backgroundColor by remember { mutableStateOf(if (darkMode) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
var backgroundColor by remember { mutableStateOf(if (darkMode) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
||||||
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(48.dp)
|
.height(55.dp)
|
||||||
.background(animatedBackgroundColor, shape)
|
.background(animatedBackgroundColor, shape)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
@@ -437,7 +438,7 @@ fun LongPressActionElement(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.padding(horizontal = 16.dp, vertical = 0.dp),
|
.padding(horizontal = 16.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
@@ -449,24 +450,18 @@ fun LongPressActionElement(
|
|||||||
.weight(1f)
|
.weight(1f)
|
||||||
.padding(start = 4.dp)
|
.padding(start = 4.dp)
|
||||||
)
|
)
|
||||||
Checkbox(
|
val floatAnimateState by animateFloatAsState(
|
||||||
checked = selected,
|
targetValue = if (selected) 1f else 0f,
|
||||||
onCheckedChange = { onClick() },
|
animationSpec = tween(durationMillis = 300)
|
||||||
colors = CheckboxDefaults.colors().copy(
|
)
|
||||||
checkedCheckmarkColor = Color(0xFF007AFF),
|
Text(
|
||||||
uncheckedCheckmarkColor = Color.Transparent,
|
text = "",
|
||||||
checkedBoxColor = Color.Transparent,
|
style = TextStyle(
|
||||||
uncheckedBoxColor = Color.Transparent,
|
fontSize = 20.sp,
|
||||||
checkedBorderColor = Color.Transparent,
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
uncheckedBorderColor = Color.Transparent,
|
color = Color(0xFF007AFF).copy(alpha = floatAnimateState)
|
||||||
disabledBorderColor = Color.Transparent,
|
|
||||||
disabledCheckedBoxColor = Color.Transparent,
|
|
||||||
disabledUncheckedBoxColor = Color.Transparent,
|
|
||||||
disabledUncheckedBorderColor = Color.Transparent
|
|
||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier.padding(end = 4.dp)
|
||||||
.height(24.dp)
|
|
||||||
.scale(1.5f),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,11 +32,9 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.Clear
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -52,12 +50,16 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextRange
|
import androidx.compose.ui.text.TextRange
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.Font
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import me.kavishdevar.librepods.R
|
import me.kavishdevar.librepods.R
|
||||||
import me.kavishdevar.librepods.composables.StyledIconButton
|
import me.kavishdevar.librepods.composables.StyledIconButton
|
||||||
@@ -81,19 +83,23 @@ fun RenameScreen(navController: NavController) {
|
|||||||
name.value = name.value.copy(selection = TextRange(name.value.text.length))
|
name.value = name.value.copy(selection = TextRange(name.value.text.length))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
|
|
||||||
StyledScaffold(
|
StyledScaffold(
|
||||||
title = stringResource(R.string.name),
|
title = stringResource(R.string.name),
|
||||||
navigationButton = {
|
navigationButton = {
|
||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { spacerHeight ->
|
) { spacerHeight ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
.layerBackdrop(backdrop)
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
Spacer(modifier = Modifier.height(spacerHeight))
|
||||||
@@ -105,10 +111,10 @@ fun RenameScreen(navController: NavController) {
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(55.dp)
|
.height(58.dp)
|
||||||
.background(
|
.background(
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
RoundedCornerShape(14.dp)
|
RoundedCornerShape(28.dp)
|
||||||
)
|
)
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
) {
|
) {
|
||||||
@@ -120,8 +126,9 @@ fun RenameScreen(navController: NavController) {
|
|||||||
ServiceManager.getService()?.setName(it.text)
|
ServiceManager.getService()?.setName(it.text)
|
||||||
},
|
},
|
||||||
textStyle = TextStyle(
|
textStyle = TextStyle(
|
||||||
color = textColor,
|
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
|
color = textColor,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
cursorBrush = SolidColor(cursorColor),
|
cursorBrush = SolidColor(cursorColor),
|
||||||
@@ -138,14 +145,15 @@ fun RenameScreen(navController: NavController) {
|
|||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
name.value = TextFieldValue("")
|
name.value = TextFieldValue("")
|
||||||
sharedPreferences.edit { putString("name", "") }
|
|
||||||
ServiceManager.getService()?.setName("")
|
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Icon(
|
Text(
|
||||||
Icons.Default.Clear,
|
text = "",
|
||||||
contentDescription = "Clear",
|
style = TextStyle(
|
||||||
tint = if (isDarkTheme) Color.White else Color.Black
|
fontSize = 16.sp,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(alpha = 0.6f)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -95,19 +97,23 @@ fun TransparencySettingsScreen(navController: NavController) {
|
|||||||
val activeTrackColor = if (isDarkTheme) Color(0xFF007AFF) else Color(0xFF3C6DF5)
|
val activeTrackColor = if (isDarkTheme) Color(0xFF007AFF) else Color(0xFF3C6DF5)
|
||||||
val thumbColor = if (isDarkTheme) Color(0xFFFFFFFF) else Color(0xFFFFFFFF)
|
val thumbColor = if (isDarkTheme) Color(0xFFFFFFFF) else Color(0xFFFFFFFF)
|
||||||
|
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
|
|
||||||
StyledScaffold(
|
StyledScaffold(
|
||||||
title = stringResource(R.string.customize_transparency_mode),
|
title = stringResource(R.string.customize_transparency_mode),
|
||||||
navigationButton = {
|
navigationButton = {
|
||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
){ spacerHeight, hazeState ->
|
){ spacerHeight, hazeState ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.hazeSource(hazeState)
|
.hazeSource(hazeState)
|
||||||
|
.layerBackdrop(backdrop)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(verticalScrollState)
|
.verticalScroll(verticalScrollState)
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
@@ -154,19 +160,15 @@ fun TransparencySettingsScreen(navController: NavController) {
|
|||||||
object : (ByteArray) -> Unit {
|
object : (ByteArray) -> Unit {
|
||||||
override fun invoke(value: ByteArray) {
|
override fun invoke(value: ByteArray) {
|
||||||
val parsed = parseTransparencySettingsResponse(value)
|
val parsed = parseTransparencySettingsResponse(value)
|
||||||
if (parsed != null) {
|
enabled.value = parsed.enabled
|
||||||
enabled.value = parsed.enabled
|
amplificationSliderValue.floatValue = parsed.netAmplification
|
||||||
amplificationSliderValue.floatValue = parsed.netAmplification
|
balanceSliderValue.floatValue = parsed.balance
|
||||||
balanceSliderValue.floatValue = parsed.balance
|
toneSliderValue.floatValue = parsed.leftTone
|
||||||
toneSliderValue.floatValue = parsed.leftTone
|
ambientNoiseReductionSliderValue.floatValue =
|
||||||
ambientNoiseReductionSliderValue.floatValue =
|
parsed.leftAmbientNoiseReduction
|
||||||
parsed.leftAmbientNoiseReduction
|
conversationBoostEnabled.value = parsed.leftConversationBoost
|
||||||
conversationBoostEnabled.value = parsed.leftConversationBoost
|
eq.value = parsed.leftEQ.copyOf()
|
||||||
eq.value = parsed.leftEQ.copyOf()
|
Log.d(TAG, "Updated transparency settings from notification")
|
||||||
Log.d(TAG, "Updated transparency settings from notification")
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, "Failed to parse transparency settings from notification")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,12 +253,7 @@ fun TransparencySettingsScreen(navController: NavController) {
|
|||||||
try {
|
try {
|
||||||
val data = attManager.read(ATTHandles.TRANSPARENCY)
|
val data = attManager.read(ATTHandles.TRANSPARENCY)
|
||||||
parsedSettings = parseTransparencySettingsResponse(data = data)
|
parsedSettings = parseTransparencySettingsResponse(data = data)
|
||||||
if (parsedSettings != null) {
|
Log.d(TAG, "Parsed settings on attempt $attempt")
|
||||||
Log.d(TAG, "Parsed settings on attempt $attempt")
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Parsing returned null on attempt $attempt")
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.w(TAG, "Read attempt $attempt failed: ${e.message}")
|
Log.w(TAG, "Read attempt $attempt failed: ${e.message}")
|
||||||
}
|
}
|
||||||
@@ -297,7 +294,7 @@ fun TransparencySettingsScreen(navController: NavController) {
|
|||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.amplification).uppercase(),
|
label = stringResource(R.string.amplification),
|
||||||
valueRange = -1f..1f,
|
valueRange = -1f..1f,
|
||||||
mutableFloatState = amplificationSliderValue,
|
mutableFloatState = amplificationSliderValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@@ -309,20 +306,20 @@ fun TransparencySettingsScreen(navController: NavController) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.balance).uppercase(),
|
label = stringResource(R.string.balance),
|
||||||
valueRange = -1f..1f,
|
valueRange = -1f..1f,
|
||||||
mutableFloatState = balanceSliderValue,
|
mutableFloatState = balanceSliderValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
balanceSliderValue.floatValue = it
|
balanceSliderValue.floatValue = it
|
||||||
},
|
},
|
||||||
snapPoints = listOf(0f),
|
snapPoints = listOf(-1f, 0f, 1f),
|
||||||
startLabel = stringResource(R.string.left),
|
startLabel = stringResource(R.string.left),
|
||||||
endLabel = stringResource(R.string.right),
|
endLabel = stringResource(R.string.right),
|
||||||
independent = true,
|
independent = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.tone).uppercase(),
|
label = stringResource(R.string.tone),
|
||||||
valueRange = -1f..1f,
|
valueRange = -1f..1f,
|
||||||
mutableFloatState = toneSliderValue,
|
mutableFloatState = toneSliderValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@@ -334,7 +331,7 @@ fun TransparencySettingsScreen(navController: NavController) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
StyledSlider(
|
StyledSlider(
|
||||||
label = stringResource(R.string.ambient_noise_reduction).uppercase(),
|
label = stringResource(R.string.ambient_noise_reduction),
|
||||||
valueRange = 0f..1f,
|
valueRange = 0f..1f,
|
||||||
mutableFloatState = ambientNoiseReductionSliderValue,
|
mutableFloatState = ambientNoiseReductionSliderValue,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@@ -356,20 +353,20 @@ fun TransparencySettingsScreen(navController: NavController) {
|
|||||||
// Only show transparency mode EQ section if SDP offset is available
|
// Only show transparency mode EQ section if SDP offset is available
|
||||||
if (isSdpOffsetAvailable.value) {
|
if (isSdpOffsetAvailable.value) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.equalizer).uppercase(),
|
text = stringResource(R.string.equalizer),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f),
|
color = textColor.copy(alpha = 0.6f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
modifier = Modifier.padding(16.dp, bottom = 4.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.SpaceBetween
|
verticalArrangement = Arrangement.SpaceBetween
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||||
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -208,6 +210,8 @@ fun TroubleshootingScreen(navController: NavController) {
|
|||||||
showBottomSheet = true
|
showBottomSheet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val backdrop = rememberLayerBackdrop()
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
@@ -217,28 +221,30 @@ fun TroubleshootingScreen(navController: NavController) {
|
|||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
onClick = { navController.popBackStack() },
|
onClick = { navController.popBackStack() },
|
||||||
icon = "",
|
icon = "",
|
||||||
darkMode = isDarkTheme
|
darkMode = isDarkTheme,
|
||||||
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
){ spacerHeight, hazeState ->
|
){ spacerHeight, hazeState ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(scrollState)
|
.layerBackdrop(backdrop)
|
||||||
.hazeSource(state = hazeState)
|
.hazeSource(state = hazeState)
|
||||||
|
.verticalScroll(scrollState)
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
Spacer(modifier = Modifier.height(spacerHeight))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.saved_logs).uppercase(),
|
text = stringResource(R.string.saved_logs),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Bold,
|
||||||
color = textColor.copy(alpha = 0.6f),
|
color = textColor.copy(alpha = 0.6f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 2.dp, top = 8.dp)
|
modifier = Modifier.padding(16.dp, bottom = 4.dp, top = 8.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
@@ -249,7 +255,7 @@ fun TroubleshootingScreen(navController: NavController) {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(
|
.background(
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
RoundedCornerShape(14.dp)
|
RoundedCornerShape(28.dp)
|
||||||
)
|
)
|
||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
@@ -266,7 +272,7 @@ fun TroubleshootingScreen(navController: NavController) {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(
|
.background(
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
RoundedCornerShape(14.dp)
|
RoundedCornerShape(28.dp)
|
||||||
)
|
)
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
) {
|
) {
|
||||||
@@ -372,14 +378,14 @@ fun TroubleshootingScreen(navController: NavController) {
|
|||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = "TROUBLESHOOTING STEPS".uppercase(),
|
text = "TROUBLESHOOTING STEPS",
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Light,
|
fontWeight = FontWeight.Light,
|
||||||
color = textColor.copy(alpha = 0.6f),
|
color = textColor.copy(alpha = 0.6f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(8.dp, bottom = 2.dp, top = 8.dp)
|
modifier = Modifier.padding(16.dp, bottom = 2.dp, top = 8.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
@@ -389,7 +395,7 @@ fun TroubleshootingScreen(navController: NavController) {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(
|
.background(
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
RoundedCornerShape(14.dp)
|
RoundedCornerShape(28.dp)
|
||||||
)
|
)
|
||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -15,12 +15,13 @@
|
|||||||
<string name="case_alt">Case</string>
|
<string name="case_alt">Case</string>
|
||||||
<string name="test">Test</string>
|
<string name="test">Test</string>
|
||||||
<string name="name">Name</string>
|
<string name="name">Name</string>
|
||||||
<string name="noise_control">Noise Control</string>
|
<string name="noise_control">Listening Mode</string>
|
||||||
<string name="off">Off</string>
|
<string name="off">Off</string>
|
||||||
<string name="transparency">Transparency</string>
|
<string name="transparency">Transparency</string>
|
||||||
<string name="adaptive">Adaptive</string>
|
<string name="adaptive">Adaptive</string>
|
||||||
<string name="noise_cancellation">Noise Cancellation</string>
|
<string name="noise_cancellation">Noise Cancellation</string>
|
||||||
<string name="press_and_hold_airpods">Press and Hold AirPods</string>
|
<string name="press_and_hold_airpods">Press and Hold AirPods</string>
|
||||||
|
<string name="press_and_hold_noise_control_description">Press and hold the stem to cycle between the selected listening modes.</string>
|
||||||
<string name="head_gestures">Head Gestures</string>
|
<string name="head_gestures">Head Gestures</string>
|
||||||
<string name="left">Left</string>
|
<string name="left">Left</string>
|
||||||
<string name="right">Right</string>
|
<string name="right">Right</string>
|
||||||
@@ -110,7 +111,7 @@
|
|||||||
<string name="press_speed">Press Speed</string>
|
<string name="press_speed">Press Speed</string>
|
||||||
<string name="press_speed_description">Adjust the speed required to press two or three times on your AirPods.</string>
|
<string name="press_speed_description">Adjust the speed required to press two or three times on your AirPods.</string>
|
||||||
<string name="press_and_hold_duration">Press and Hold Duration</string>
|
<string name="press_and_hold_duration">Press and Hold Duration</string>
|
||||||
<string name="press_and_hold_duration_description">Adjust the duration required to press and hold on your AirPods</string>
|
<string name="press_and_hold_duration_description">Adjust the duration required to press and hold on your AirPods.</string>
|
||||||
<string name="volume_swipe_speed">Volume Swipe Speed</string>
|
<string name="volume_swipe_speed">Volume Swipe Speed</string>
|
||||||
<string name="volume_swipe_speed_description">To prevent unintended volume adjustments, select preferred wait time between swipes.</string>
|
<string name="volume_swipe_speed_description">To prevent unintended volume adjustments, select preferred wait time between swipes.</string>
|
||||||
<string name="equalizer">Equalizer</string>
|
<string name="equalizer">Equalizer</string>
|
||||||
@@ -133,7 +134,7 @@
|
|||||||
<string name="ambient_noise_reduction">Ambient Noise Reduction</string>
|
<string name="ambient_noise_reduction">Ambient Noise Reduction</string>
|
||||||
<string name="conversation_boost">Conversation Boost</string>
|
<string name="conversation_boost">Conversation Boost</string>
|
||||||
<string name="conversation_boost_description">Conversation Boost focuses your AirPods Pro on the person talking in front of you, making it easier to hear in a face-to-face conversation.</string>
|
<string name="conversation_boost_description">Conversation Boost focuses your AirPods Pro on the person talking in front of you, making it easier to hear in a face-to-face conversation.</string>
|
||||||
<string name="hearing_aid_description">AirPods can use the results of a hearing test to make adjustments that improve the clarity of voices and sounds around you. \n\n Hearing Aid is only intended for people with perceived mild to moderate hearing loss.</string>
|
<string name="hearing_aid_description">AirPods can use the results of a hearing test to make adjustments that improve the clarity of voices and sounds around you.\n\nHearing Aid is only intended for people with perceived mild to moderate hearing loss.</string>
|
||||||
<string name="media_assist">Media Assist</string>
|
<string name="media_assist">Media Assist</string>
|
||||||
<string name="media_assist_description">AirPods Pro can use the results of a hearing test to make adjustments that improve the clarity of music, video, and calls.</string>
|
<string name="media_assist_description">AirPods Pro can use the results of a hearing test to make adjustments that improve the clarity of music, video, and calls.</string>
|
||||||
<string name="adjust_media">Adjust Music and Video</string>
|
<string name="adjust_media">Adjust Music and Video</string>
|
||||||
@@ -174,4 +175,5 @@
|
|||||||
<string name="must_be_32_hex_chars">Must be exactly 32 hex characters</string>
|
<string name="must_be_32_hex_chars">Must be exactly 32 hex characters</string>
|
||||||
<string name="error_converting_hex">Error converting hex:</string>
|
<string name="error_converting_hex">Error converting hex:</string>
|
||||||
<string name="found_offset_restart_bluetooth">Found offset please restart the Bluetooth process</string>
|
<string name="found_offset_restart_bluetooth">Found offset please restart the Bluetooth process</string>
|
||||||
|
<string name="digital_assistant">Digital Assistant</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user