mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-02-01 07:39:11 +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
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.audio).uppercase(),
|
||||
text = stringResource(R.string.audio),
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
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)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(14.dp))
|
||||
.clip(RoundedCornerShape(28.dp))
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(top = 2.dp)
|
||||
) {
|
||||
|
||||
@@ -76,11 +76,12 @@ fun AudioSettings(navController: NavController) {
|
||||
controlCommandIdentifier = AACPManager.Companion.ControlCommandIdentifiers.ADAPTIVE_VOLUME_CONFIG,
|
||||
independent = false
|
||||
)
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp, end = 0.dp)
|
||||
.padding(horizontal= 12.dp)
|
||||
)
|
||||
|
||||
StyledToggle(
|
||||
@@ -90,10 +91,10 @@ fun AudioSettings(navController: NavController) {
|
||||
independent = false
|
||||
)
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp, end = 0.dp)
|
||||
.padding(horizontal= 12.dp)
|
||||
)
|
||||
|
||||
StyledToggle(
|
||||
@@ -103,10 +104,10 @@ fun AudioSettings(navController: NavController) {
|
||||
independent = false
|
||||
)
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp, end = 0.dp)
|
||||
.padding(horizontal= 12.dp)
|
||||
)
|
||||
|
||||
NavigationButton(
|
||||
|
||||
@@ -27,7 +27,9 @@ import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -71,7 +73,6 @@ fun BatteryIndicator(
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(12.dp)
|
||||
.background(backgroundColor), // just for haze to work
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
@@ -85,7 +86,7 @@ fun BatteryIndicator(
|
||||
color = batteryFillColor,
|
||||
gapSize = 0.dp,
|
||||
strokeCap = StrokeCap.Round,
|
||||
strokeWidth = 2.dp,
|
||||
strokeWidth = 4.dp,
|
||||
trackColor = if (isDarkTheme) Color(0xFF0E0E0F) else Color(0xFFE3E3E8)
|
||||
)
|
||||
|
||||
@@ -101,6 +102,8 @@ fun BatteryIndicator(
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
Text(
|
||||
text = "$prefix $batteryPercentage%",
|
||||
color = batteryTextColor,
|
||||
|
||||
@@ -146,7 +146,7 @@ fun BatteryView(service: AirPodsService, preview: Boolean = false) {
|
||||
contentDescription = stringResource(R.string.buds),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp)
|
||||
.padding(8.dp)
|
||||
)
|
||||
if (
|
||||
leftCharging == rightCharging &&
|
||||
@@ -202,7 +202,7 @@ fun BatteryView(service: AirPodsService, preview: Boolean = false) {
|
||||
contentDescription = stringResource(R.string.case_alt),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp)
|
||||
.padding(8.dp)
|
||||
)
|
||||
if (caseLevel > 0 || case?.status != BatteryStatus.DISCONNECTED) {
|
||||
BatteryIndicator(
|
||||
|
||||
@@ -32,12 +32,8 @@ 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.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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.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.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -76,19 +74,19 @@ fun CallControlSettings(hazeState: HazeState) {
|
||||
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.call_controls).uppercase(),
|
||||
text = stringResource(R.string.call_controls),
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = textColor.copy(alpha = 0.6f)
|
||||
),
|
||||
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
||||
modifier = Modifier.padding(16.dp, bottom = 4.dp)
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(top = 2.dp)
|
||||
) {
|
||||
val service = ServiceManager.getService()!!
|
||||
@@ -169,8 +167,8 @@ fun CallControlSettings(hazeState: HazeState) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 12.dp, end = 12.dp)
|
||||
.height(50.dp),
|
||||
.padding(horizontal = 16.dp)
|
||||
.height(58.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
@@ -187,17 +185,17 @@ fun CallControlSettings(hazeState: HazeState) {
|
||||
)
|
||||
}
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp, end = 0.dp)
|
||||
.padding(horizontal = 12.dp)
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 12.dp, end = 12.dp)
|
||||
.height(50.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
.height(58.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures { offset ->
|
||||
val now = System.currentTimeMillis()
|
||||
@@ -276,14 +274,21 @@ fun CallControlSettings(hazeState: HazeState) {
|
||||
) {
|
||||
Text(
|
||||
text = singlePressAction,
|
||||
fontSize = 16.sp,
|
||||
color = textColor.copy(alpha = 0.8f)
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
color = textColor.copy(alpha = 0.8f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
)
|
||||
)
|
||||
Icon(
|
||||
Icons.Default.KeyboardArrowDown,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(18.dp),
|
||||
tint = textColor.copy(alpha = 0.6f)
|
||||
Text(
|
||||
text = "",
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
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(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp, end = 0.dp)
|
||||
.padding(horizontal = 12.dp)
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 12.dp, end = 12.dp)
|
||||
.height(50.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
.height(58.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures { offset ->
|
||||
val now = System.currentTimeMillis()
|
||||
@@ -404,14 +409,21 @@ fun CallControlSettings(hazeState: HazeState) {
|
||||
) {
|
||||
Text(
|
||||
text = doublePressAction,
|
||||
fontSize = 16.sp,
|
||||
color = textColor.copy(alpha = 0.8f)
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
color = textColor.copy(alpha = 0.8f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
)
|
||||
)
|
||||
Icon(
|
||||
Icons.Default.KeyboardArrowDown,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(18.dp),
|
||||
tint = textColor.copy(alpha = 0.6f)
|
||||
Text(
|
||||
text = "",
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
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.refraction
|
||||
import com.kyant.backdrop.highlight.Highlight
|
||||
import com.kyant.backdrop.highlight.HighlightStyle
|
||||
import kotlinx.coroutines.launch
|
||||
import me.kavishdevar.librepods.R
|
||||
import me.kavishdevar.librepods.utils.inspectDragGestures
|
||||
@@ -143,7 +142,9 @@ half4 main(float2 coord) {
|
||||
.drawBackdrop(
|
||||
backdrop,
|
||||
{ RoundedCornerShape(48f.dp) },
|
||||
highlight = { Highlight { HighlightStyle.Solid } },
|
||||
highlight = {
|
||||
Highlight.SolidDefault
|
||||
},
|
||||
onDrawSurface = { drawRect(containerColor) },
|
||||
effects = {
|
||||
colorControls(
|
||||
@@ -153,7 +154,7 @@ half4 main(float2 coord) {
|
||||
blur(if (isLightTheme) 16f.dp.toPx() else 8f.dp.toPx())
|
||||
refraction(24f.dp.toPx(), 48f.dp.toPx(), true)
|
||||
},
|
||||
layer = {
|
||||
layerBlock = {
|
||||
val width = size.width
|
||||
val height = size.height
|
||||
|
||||
@@ -273,16 +274,6 @@ half4 main(float2 coord) {
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
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(
|
||||
onClick = onDismiss,
|
||||
backdrop = backdrop,
|
||||
@@ -295,16 +286,6 @@ half4 main(float2 coord) {
|
||||
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(
|
||||
onClick = onConfirm,
|
||||
backdrop = backdrop,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
package me.kavishdevar.librepods.composables
|
||||
|
||||
import android.content.Context.MODE_PRIVATE
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
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.tooling.preview.Preview
|
||||
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.utils.AACPManager
|
||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||
|
||||
@Composable
|
||||
fun ConnectionSettings() {
|
||||
@@ -48,7 +47,7 @@ fun ConnectionSettings() {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(top = 2.dp)
|
||||
) {
|
||||
StyledToggle(
|
||||
@@ -59,10 +58,10 @@ fun ConnectionSettings() {
|
||||
independent = false
|
||||
)
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
modifier = Modifier
|
||||
.padding(start = 12.dp, end = 0.dp)
|
||||
.padding(horizontal= 12.dp)
|
||||
)
|
||||
|
||||
StyledToggle(
|
||||
|
||||
@@ -32,11 +32,7 @@ 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.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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.platform.LocalDensity
|
||||
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.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -75,7 +74,7 @@ fun MicrophoneSettings(hazeState: HazeState) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(top = 2.dp)
|
||||
) {
|
||||
val service = ServiceManager.getService()!!
|
||||
@@ -141,8 +140,8 @@ fun MicrophoneSettings(hazeState: HazeState) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 12.dp, end = 12.dp)
|
||||
.height(55.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
.height(58.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures { offset ->
|
||||
val now = System.currentTimeMillis()
|
||||
@@ -214,8 +213,11 @@ fun MicrophoneSettings(hazeState: HazeState) {
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.microphone_mode),
|
||||
fontSize = 16.sp,
|
||||
color = textColor,
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
color = textColor,
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
),
|
||||
modifier = Modifier.padding(bottom = 4.dp)
|
||||
)
|
||||
Box(
|
||||
@@ -228,14 +230,21 @@ fun MicrophoneSettings(hazeState: HazeState) {
|
||||
) {
|
||||
Text(
|
||||
text = selectedMode,
|
||||
fontSize = 16.sp,
|
||||
color = textColor.copy(alpha = 0.8f)
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
color = textColor.copy(alpha = 0.8f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
)
|
||||
)
|
||||
Icon(
|
||||
Icons.Default.KeyboardArrowDown,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = textColor.copy(alpha = 0.6f)
|
||||
Text(
|
||||
text = "",
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
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
|
||||
*
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
@@ -23,75 +23,105 @@ 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.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
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.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.graphics.Color
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
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.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavController
|
||||
|
||||
import me.kavishdevar.librepods.R
|
||||
|
||||
@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()
|
||||
var backgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
||||
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.background(animatedBackgroundColor, RoundedCornerShape(if (independent) 14.dp else 0.dp))
|
||||
.height(55.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onPress = {
|
||||
backgroundColor = if (isDarkTheme) Color(0x40888888) else Color(0x40D9D9D9)
|
||||
tryAwaitRelease()
|
||||
backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||
},
|
||||
onTap = {
|
||||
if (onClick != null) onClick() else navController.navigate(to)
|
||||
}
|
||||
Column {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.background(animatedBackgroundColor, RoundedCornerShape(if (independent) 28.dp else 0.dp))
|
||||
.height(58.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onPress = {
|
||||
backgroundColor = if (isDarkTheme) Color(0x40888888) else Color(0x40D9D9D9)
|
||||
tryAwaitRelease()
|
||||
backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||
},
|
||||
onTap = {
|
||||
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 = name,
|
||||
modifier = Modifier.padding(16.dp),
|
||||
color = if (isDarkTheme) Color.White else Color.Black
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
IconButton(
|
||||
onClick = { if (onClick != null) onClick() else navController.navigate(to) },
|
||||
colors = IconButtonDefaults.iconButtonColors(
|
||||
containerColor = Color.Transparent,
|
||||
contentColor = if (isDarkTheme) Color.White else Color.Black
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(start = 16.dp)
|
||||
.fillMaxHeight()
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
Icon(
|
||||
imageVector = Icons.Default.KeyboardArrowRight,
|
||||
contentDescription = name
|
||||
Text(
|
||||
text = "",
|
||||
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.6f)
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(start = if (currentState != null) 6.dp else 0.dp)
|
||||
)
|
||||
}
|
||||
if (description != null) {
|
||||
Text(
|
||||
text = description,
|
||||
style = TextStyle(
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(alpha = 0.6f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
),
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -101,4 +131,4 @@ fun NavigationButton(to: String, name: String, navController: NavController, onC
|
||||
@Composable
|
||||
fun NavigationButtonPreview() {
|
||||
NavigationButton("to", "Name", NavController(LocalContext.current))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,10 +181,10 @@ fun NoiseControlSettings(
|
||||
}
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.noise_control).uppercase(),
|
||||
text = stringResource(R.string.noise_control),
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = textColor.copy(alpha = 0.6f),
|
||||
),
|
||||
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
||||
@@ -241,7 +241,7 @@ fun NoiseControlSettings(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(60.dp)
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
@@ -334,7 +334,7 @@ fun NoiseControlSettings(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(3.dp)
|
||||
.background(selectedBackground, RoundedCornerShape(12.dp))
|
||||
.background(selectedBackground, RoundedCornerShape(26.dp))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -400,7 +400,6 @@ fun NoiseControlSettings(
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 4.dp)
|
||||
.padding(top = 4.dp)
|
||||
) {
|
||||
if (offListeningMode.value) {
|
||||
@@ -408,7 +407,6 @@ fun NoiseControlSettings(
|
||||
text = stringResource(R.string.off),
|
||||
style = TextStyle(fontSize = 12.sp, color = textColor),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
}
|
||||
@@ -416,21 +414,18 @@ fun NoiseControlSettings(
|
||||
text = stringResource(R.string.transparency),
|
||||
style = TextStyle(fontSize = 12.sp, color = textColor),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.adaptive),
|
||||
style = TextStyle(fontSize = 12.sp, color = textColor),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.noise_cancellation),
|
||||
style = TextStyle(fontSize = 12.sp, color = textColor),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,34 +19,21 @@
|
||||
package me.kavishdevar.librepods.composables
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
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.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
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.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
@@ -65,12 +52,6 @@ fun PressAndHoldSettings(navController: NavController) {
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val textColor = if (isDarkTheme) Color.White else Color.Black
|
||||
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 sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
@@ -91,14 +72,14 @@ fun PressAndHoldSettings(navController: NavController) {
|
||||
}
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.press_and_hold_airpods).uppercase(),
|
||||
text = stringResource(R.string.press_and_hold_airpods),
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = textColor.copy(alpha = 0.6f),
|
||||
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))
|
||||
@@ -106,126 +87,33 @@ fun PressAndHoldSettings(navController: NavController) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.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(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(50.dp)
|
||||
.background(animatedLeftBackgroundColor, RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp))
|
||||
.pointerInput(Unit) {
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
NavigationButton(
|
||||
to = "long_press/Left",
|
||||
name = stringResource(R.string.left),
|
||||
navController = navController,
|
||||
independent = false,
|
||||
currentState = leftActionText,
|
||||
)
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = dividerColor,
|
||||
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
|
||||
fun PressAndHoldSettingsPreview() {
|
||||
PressAndHoldSettings(navController = NavController(LocalContext.current))
|
||||
|
||||
@@ -74,7 +74,8 @@ fun StyledButton(
|
||||
isInteractive: Boolean = true,
|
||||
tint: Color = Color.Unspecified,
|
||||
surfaceColor: Color = Color.Unspecified,
|
||||
content: @Composable RowScope.() -> Unit
|
||||
maxScale: Float = 0.1f,
|
||||
content: @Composable RowScope.() -> Unit,
|
||||
) {
|
||||
val animationScope = rememberCoroutineScope()
|
||||
val progressAnimation = remember { Animatable(0f) }
|
||||
@@ -113,7 +114,7 @@ half4 main(float2 coord) {
|
||||
effects = {
|
||||
blur(16f.dp.toPx())
|
||||
},
|
||||
layer = null,
|
||||
layerBlock = null,
|
||||
onDrawSurface = {
|
||||
if (tint.isSpecified) {
|
||||
drawRect(tint, blendMode = BlendMode.Hue)
|
||||
@@ -147,12 +148,11 @@ half4 main(float2 coord) {
|
||||
blur(2f.dp.toPx())
|
||||
refraction(12f.dp.toPx(), 24f.dp.toPx())
|
||||
},
|
||||
layer = {
|
||||
layerBlock = {
|
||||
val width = size.width
|
||||
val height = size.height
|
||||
|
||||
val progress = progressAnimation.value
|
||||
val maxScale = 0.1f
|
||||
val scale = lerp(1f, 1f + maxScale, progress)
|
||||
|
||||
val maxOffset = size.minDimension
|
||||
|
||||
@@ -230,7 +230,7 @@ fun StyledDropdown(
|
||||
|
||||
if (index != options.lastIndex) {
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
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.VisibilityThreshold
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
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.fastCoerceIn
|
||||
import androidx.compose.ui.util.lerp
|
||||
import com.kyant.backdrop.backdrops.LayerBackdrop
|
||||
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||
import com.kyant.backdrop.drawBackdrop
|
||||
import com.kyant.backdrop.effects.blur
|
||||
import com.kyant.backdrop.effects.refractionWithDispersion
|
||||
import com.kyant.backdrop.highlight.Highlight
|
||||
import com.kyant.backdrop.shadow.Shadow
|
||||
@@ -79,6 +82,8 @@ fun StyledIconButton(
|
||||
icon: String,
|
||||
darkMode: Boolean,
|
||||
tint: Color = Color.Unspecified,
|
||||
backdrop: LayerBackdrop = rememberLayerBackdrop(),
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val animationScope = rememberCoroutineScope()
|
||||
val progressAnimationSpec = spring(0.5f, 300f, 0.001f)
|
||||
@@ -110,26 +115,23 @@ half4 main(float2 coord) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
TextButton(
|
||||
onClick = onClick,
|
||||
shape = RoundedCornerShape(56.dp),
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.padding(horizontal = 12.dp)
|
||||
.drawBackdrop(
|
||||
backdrop = rememberLayerBackdrop(),
|
||||
backdrop = backdrop,
|
||||
shape = { RoundedCornerShape(56.dp) },
|
||||
highlight = {
|
||||
val progress = progressAnimation.value
|
||||
Highlight.AmbientDefault.copy(alpha = progress.coerceIn(0.45f, 1f))
|
||||
},
|
||||
highlight = { Highlight.AmbientDefault.copy(alpha = if (isDarkTheme) 1f else 0f) },
|
||||
shadow = {
|
||||
Shadow(
|
||||
radius = 4f.dp,
|
||||
color = Color.Black.copy(0.08f)
|
||||
radius = 48f.dp,
|
||||
color = Color.Black.copy(if (isDarkTheme) 0.08f else 0.4f)
|
||||
)
|
||||
},
|
||||
layer = {
|
||||
layerBlock = {
|
||||
val width = size.width
|
||||
val height = size.height
|
||||
|
||||
@@ -182,7 +184,7 @@ half4 main(float2 coord) {
|
||||
drawLayer(innerShadowLayer)
|
||||
|
||||
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 = {
|
||||
@@ -218,6 +220,7 @@ half4 main(float2 coord) {
|
||||
},
|
||||
effects = {
|
||||
refractionWithDispersion(6f.dp.toPx(), size.height / 2f)
|
||||
blur(24f, TileMode.Decal)
|
||||
},
|
||||
)
|
||||
.pointerInput(animationScope) {
|
||||
|
||||
@@ -31,12 +31,14 @@ import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -84,6 +86,7 @@ import com.kyant.backdrop.highlight.Highlight
|
||||
import com.kyant.backdrop.shadow.Shadow
|
||||
import kotlinx.coroutines.launch
|
||||
import me.kavishdevar.librepods.R
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Composable
|
||||
@@ -136,23 +139,26 @@ fun StyledSlider(
|
||||
|
||||
val content = @Composable {
|
||||
Box(
|
||||
Modifier.fillMaxWidth(if (startIcon == null && endIcon == null) 0.95f else 1f)
|
||||
) {
|
||||
Modifier
|
||||
.fillMaxWidth(if (startIcon == null && endIcon == null) 0.95f else 1f)
|
||||
) {
|
||||
Box(
|
||||
Modifier
|
||||
.padding(vertical = 4.dp)
|
||||
.layerBackdrop(sliderBackdrop)
|
||||
.fillMaxWidth()) {
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(1f)
|
||||
.padding(vertical = 12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
if (startLabel != null || endLabel != null) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 8.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
@@ -174,80 +180,119 @@ fun StyledSlider(
|
||||
)
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
}
|
||||
|
||||
Row(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 4.dp)
|
||||
.then(if (startIcon == null && endIcon == null) Modifier.padding(horizontal = 12.dp) else Modifier),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(0.dp)
|
||||
.then(if (startIcon == null && endIcon == null) Modifier.padding(horizontal = 8.dp) else Modifier),
|
||||
) {
|
||||
if (startIcon != null) {
|
||||
Text(
|
||||
text = startIcon,
|
||||
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
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(0.dp)
|
||||
) {
|
||||
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 (startIcon != null) {
|
||||
Text(
|
||||
text = startIcon,
|
||||
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()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
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)
|
||||
)
|
||||
}
|
||||
Box(
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.onSizeChanged { trackWidthState.floatValue = it.width.toFloat() }
|
||||
.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
|
||||
.graphicsLayer {
|
||||
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 =
|
||||
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(
|
||||
rememberDraggableState { delta ->
|
||||
@@ -305,7 +350,7 @@ fun StyledSlider(
|
||||
color = Color.Black.copy(0.05f)
|
||||
)
|
||||
},
|
||||
layer = {
|
||||
layerBlock = {
|
||||
val progress = progressAnimation.value
|
||||
val scale = lerp(1f, 1.5f, progress)
|
||||
scaleX = scale
|
||||
@@ -361,20 +406,20 @@ fun StyledSlider(
|
||||
text = label,
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = labelTextColor.copy(alpha = 0.6f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
),
|
||||
modifier = Modifier.padding(8.dp)
|
||||
modifier = Modifier.padding(horizontal = 18.dp, vertical = 4.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(horizontal = 8.dp, vertical = 0.dp)
|
||||
.heightIn(min = 55.dp),
|
||||
.heightIn(min = 58.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
content()
|
||||
@@ -390,7 +435,7 @@ fun StyledSlider(
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
),
|
||||
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 {
|
||||
val nearest = points.minByOrNull { kotlin.math.abs(it - value) } ?: value
|
||||
return if (kotlin.math.abs(nearest - value) <= threshold) nearest else value
|
||||
val nearest = points.minByOrNull { abs(it - value) } ?: value
|
||||
return if (abs(nearest - value) <= threshold) nearest else value
|
||||
}
|
||||
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@@ -426,9 +471,11 @@ fun StyledSliderPreview() {
|
||||
a.floatValue = it
|
||||
},
|
||||
valueRange = 0f..2f,
|
||||
snapPoints = listOf(0f, 0.5f, 1f, 1.5f, 2f),
|
||||
snapThreshold = 0.1f,
|
||||
independent = true,
|
||||
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.BlurEffect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Paint
|
||||
import androidx.compose.ui.graphics.TileMode
|
||||
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.graphicsLayer
|
||||
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.highlight.Highlight
|
||||
import com.kyant.backdrop.shadow.Shadow
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
@@ -76,16 +79,17 @@ fun StyledSwitch(
|
||||
checked: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
enabled: Boolean = true,
|
||||
indpendent: Boolean = true,
|
||||
) {
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
|
||||
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 trackWidth = 70.dp
|
||||
val trackHeight = 31.dp
|
||||
val thumbHeight = 27.dp
|
||||
val thumbWidth = 36.dp
|
||||
val trackWidth = 64.dp
|
||||
val trackHeight = 28.dp
|
||||
val thumbHeight = 24.dp
|
||||
val thumbWidth = 39.dp
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
val switchBackdrop = rememberLayerBackdrop()
|
||||
@@ -97,18 +101,23 @@ fun StyledSwitch(
|
||||
val density = LocalDensity.current
|
||||
val animationScope = rememberCoroutineScope()
|
||||
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 innerShadowLayer = rememberGraphicsLayer().apply {
|
||||
compositingStrategy = CompositingStrategy.Offscreen
|
||||
}
|
||||
val animatedTrackColor = remember { Animatable(if (checked) onColor else offColor) }
|
||||
|
||||
LaunchedEffect(checked) {
|
||||
val targetColor = if (checked) onColor else offColor
|
||||
animatedTrackColor.animateTo(targetColor, colorAnimationSpec)
|
||||
val targetFrac = if (checked) 1f else 0f
|
||||
animatedFraction.animateTo(targetFrac, progressAnimationSpec)
|
||||
coroutineScope {
|
||||
launch {
|
||||
val targetColor = if (checked) onColor else offColor
|
||||
animatedTrackColor.animateTo(targetColor, colorAnimationSpec)
|
||||
}
|
||||
launch {
|
||||
val targetFrac = if (checked) 1f else 0f
|
||||
animatedFraction.animateTo(targetFrac, progressAnimationSpec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Box(
|
||||
@@ -136,7 +145,7 @@ fun StyledSwitch(
|
||||
.then(if (enabled) Modifier.draggable(
|
||||
rememberDraggableState { delta ->
|
||||
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 {
|
||||
animatedFraction.snapTo(newFraction)
|
||||
}
|
||||
@@ -155,10 +164,12 @@ fun StyledSwitch(
|
||||
},
|
||||
onDragStopped = {
|
||||
animationScope.launch {
|
||||
progressAnimation.animateTo(0f, progressAnimationSpec)
|
||||
val snappedFraction = if (animatedFraction.value >= 0.5f) 1f else 0f
|
||||
animatedFraction.animateTo(snappedFraction, progressAnimationSpec)
|
||||
onCheckedChange(snappedFraction >= 0.5f)
|
||||
coroutineScope {
|
||||
launch { progressAnimation.animateTo(0f, progressAnimationSpec) }
|
||||
launch { animatedFraction.animateTo(snappedFraction, progressAnimationSpec) }
|
||||
}
|
||||
}
|
||||
}
|
||||
) else Modifier)
|
||||
@@ -175,12 +186,27 @@ fun StyledSwitch(
|
||||
color = Color.Black.copy(0.05f)
|
||||
)
|
||||
},
|
||||
layer = {
|
||||
layerBlock = {
|
||||
val progress = progressAnimation.value
|
||||
val scale = lerp(1f, 2f, progress)
|
||||
val scale = lerp(1f, 1.6f, progress)
|
||||
scaleX = 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 = {
|
||||
val progress = progressAnimation.value.fastCoerceIn(0f, 1f)
|
||||
|
||||
@@ -224,12 +250,12 @@ fun StyledSwitch(
|
||||
@Composable
|
||||
fun StyledSwitchPreview() {
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val backgroundColor = if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7)
|
||||
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFF2F2F7)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(backgroundColor)
|
||||
.width(100.dp)
|
||||
.height(100.dp),
|
||||
.height(400.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val checked = remember { mutableStateOf(true) }
|
||||
@@ -238,13 +264,14 @@ fun StyledSwitchPreview() {
|
||||
onCheckedChange = {
|
||||
checked.value = it
|
||||
},
|
||||
enabled = true
|
||||
enabled = true,
|
||||
indpendent = false
|
||||
)
|
||||
LaunchedEffect(Unit) {
|
||||
delay(1000)
|
||||
checked.value = false
|
||||
delay(1000)
|
||||
checked.value = true
|
||||
}
|
||||
// LaunchedEffect(Unit) {
|
||||
// delay(1000)
|
||||
// checked.value = false
|
||||
// delay(1000)
|
||||
// checked.value = true
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ fun StyledToggle(
|
||||
sharedPreferenceKey: String? = null,
|
||||
sharedPreferences: SharedPreferences? = null,
|
||||
independent: Boolean = true,
|
||||
enabled: Boolean = true,
|
||||
onCheckedChange: ((Boolean) -> Unit)? = null,
|
||||
) {
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
@@ -82,7 +83,9 @@ fun StyledToggle(
|
||||
var checked by checkedState
|
||||
var backgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
||||
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
||||
|
||||
if (sharedPreferenceKey != null && sharedPreferences != null) {
|
||||
checked = sharedPreferences.getBoolean(sharedPreferenceKey, checked)
|
||||
}
|
||||
fun cb() {
|
||||
if (sharedPreferences != null) {
|
||||
if (sharedPreferenceKey == null) {
|
||||
@@ -101,15 +104,16 @@ fun StyledToggle(
|
||||
text = title,
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
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(
|
||||
modifier = Modifier
|
||||
.background(animatedBackgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(animatedBackgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(4.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onPress = {
|
||||
@@ -120,8 +124,10 @@ fun StyledToggle(
|
||||
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||
},
|
||||
onTap = {
|
||||
checked = !checked
|
||||
cb()
|
||||
if (enabled) {
|
||||
checked = !checked
|
||||
cb()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -145,10 +151,14 @@ fun StyledToggle(
|
||||
)
|
||||
StyledSwitch(
|
||||
checked = checked,
|
||||
enabled = enabled,
|
||||
onCheckedChange = {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
if (enabled) {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
},
|
||||
indpendent = true
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -156,7 +166,7 @@ fun StyledToggle(
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
.background(if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7))
|
||||
) {
|
||||
Text(
|
||||
@@ -177,10 +187,10 @@ fun StyledToggle(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
shape = RoundedCornerShape(14.dp),
|
||||
shape = RoundedCornerShape(28.dp),
|
||||
color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent
|
||||
)
|
||||
.padding(horizontal = 12.dp, vertical = 12.dp)
|
||||
.padding(16.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onPress = {
|
||||
@@ -194,8 +204,10 @@ fun StyledToggle(
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
checked = !checked
|
||||
cb()
|
||||
if (enabled) {
|
||||
checked = !checked
|
||||
cb()
|
||||
}
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
@@ -206,25 +218,35 @@ fun StyledToggle(
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
fontSize = 16.sp,
|
||||
color = textColor
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||
fontWeight = FontWeight.Normal,
|
||||
color = textColor
|
||||
)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
if (description != null) {
|
||||
Text(
|
||||
text = description,
|
||||
fontSize = 12.sp,
|
||||
color = textColor.copy(0.6f),
|
||||
lineHeight = 14.sp,
|
||||
style = TextStyle(
|
||||
fontSize = 12.sp,
|
||||
color = textColor.copy(0.6f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
StyledSwitch(
|
||||
checked = checked,
|
||||
enabled = enabled,
|
||||
onCheckedChange = {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
if (enabled) {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
},
|
||||
indpendent = false
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -237,6 +259,7 @@ fun StyledToggle(
|
||||
description: String? = null,
|
||||
controlCommandIdentifier: AACPManager.Companion.ControlCommandIdentifiers,
|
||||
independent: Boolean = true,
|
||||
enabled: Boolean = true,
|
||||
sharedPreferenceKey: String? = null,
|
||||
sharedPreferences: SharedPreferences? = null,
|
||||
onCheckedChange: ((Boolean) -> Unit)? = null,
|
||||
@@ -291,15 +314,16 @@ fun StyledToggle(
|
||||
text = title,
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
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(
|
||||
modifier = Modifier
|
||||
.background(animatedBackgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(animatedBackgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(4.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onPress = {
|
||||
@@ -310,8 +334,10 @@ fun StyledToggle(
|
||||
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||
},
|
||||
onTap = {
|
||||
checked = !checked
|
||||
cb()
|
||||
if (enabled) {
|
||||
checked = !checked
|
||||
cb()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -335,10 +361,14 @@ fun StyledToggle(
|
||||
)
|
||||
StyledSwitch(
|
||||
checked = checked,
|
||||
enabled = enabled,
|
||||
onCheckedChange = {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
if (enabled) {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
},
|
||||
indpendent = true
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -346,7 +376,7 @@ fun StyledToggle(
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
.background(if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7))
|
||||
) {
|
||||
Text(
|
||||
@@ -367,10 +397,10 @@ fun StyledToggle(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
shape = RoundedCornerShape(14.dp),
|
||||
shape = RoundedCornerShape(28.dp),
|
||||
color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent
|
||||
)
|
||||
.padding(horizontal = 12.dp, vertical = 12.dp)
|
||||
.padding(16.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onPress = {
|
||||
@@ -384,8 +414,10 @@ fun StyledToggle(
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
checked = !checked
|
||||
cb()
|
||||
if (enabled) {
|
||||
checked = !checked
|
||||
cb()
|
||||
}
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
@@ -396,25 +428,35 @@ fun StyledToggle(
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
fontSize = 16.sp,
|
||||
color = textColor
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||
fontWeight = FontWeight.Normal,
|
||||
color = textColor
|
||||
)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
if (description != null) {
|
||||
Text(
|
||||
text = description,
|
||||
fontSize = 12.sp,
|
||||
color = textColor.copy(0.6f),
|
||||
lineHeight = 14.sp,
|
||||
style = TextStyle(
|
||||
fontSize = 12.sp,
|
||||
color = textColor.copy(0.6f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
StyledSwitch(
|
||||
checked = checked,
|
||||
enabled = enabled,
|
||||
onCheckedChange = {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
if (enabled) {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
},
|
||||
indpendent = false
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -427,6 +469,7 @@ fun StyledToggle(
|
||||
description: String? = null,
|
||||
attHandle: ATTHandles,
|
||||
independent: Boolean = true,
|
||||
enabled: Boolean = true,
|
||||
sharedPreferenceKey: String? = null,
|
||||
sharedPreferences: SharedPreferences? = null,
|
||||
onCheckedChange: ((Boolean) -> Unit)? = null,
|
||||
@@ -509,15 +552,16 @@ fun StyledToggle(
|
||||
text = title,
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
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(
|
||||
modifier = Modifier
|
||||
.background(animatedBackgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(animatedBackgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(4.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onPress = {
|
||||
@@ -528,8 +572,10 @@ fun StyledToggle(
|
||||
if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||
},
|
||||
onTap = {
|
||||
checked = !checked
|
||||
cb()
|
||||
if (enabled) {
|
||||
checked = !checked
|
||||
cb()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -553,10 +599,14 @@ fun StyledToggle(
|
||||
)
|
||||
StyledSwitch(
|
||||
checked = checked,
|
||||
enabled = enabled,
|
||||
onCheckedChange = {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
if (enabled) {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
},
|
||||
indpendent = true
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -564,7 +614,7 @@ fun StyledToggle(
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
.background(if (isDarkTheme) Color(0xFF000000) else Color(0xFFF2F2F7))
|
||||
) {
|
||||
Text(
|
||||
@@ -585,10 +635,10 @@ fun StyledToggle(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
shape = RoundedCornerShape(14.dp),
|
||||
shape = RoundedCornerShape(28.dp),
|
||||
color = if (isPressed.value) Color(0xFFE0E0E0) else Color.Transparent
|
||||
)
|
||||
.padding(horizontal = 12.dp, vertical = 12.dp)
|
||||
.padding(16.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onPress = {
|
||||
@@ -602,8 +652,10 @@ fun StyledToggle(
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
checked = !checked
|
||||
cb()
|
||||
if (enabled) {
|
||||
checked = !checked
|
||||
cb()
|
||||
}
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
@@ -629,10 +681,14 @@ fun StyledToggle(
|
||||
}
|
||||
StyledSwitch(
|
||||
checked = checked,
|
||||
enabled = enabled,
|
||||
onCheckedChange = {
|
||||
checked = it
|
||||
cb()
|
||||
}
|
||||
if (enabled) {
|
||||
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.RoundedCornerShape
|
||||
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.CheckboxDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.SliderDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
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.sp
|
||||
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.hazeSource
|
||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||
@@ -149,13 +147,16 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
||||
}
|
||||
}
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
|
||||
StyledScaffold(
|
||||
title = stringResource(R.string.accessibility),
|
||||
navigationButton = {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
},
|
||||
) { spacerHeight, hazeState ->
|
||||
@@ -163,6 +164,7 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.hazeSource(hazeState)
|
||||
.layerBackdrop(backdrop)
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
@@ -370,7 +372,7 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
||||
)
|
||||
|
||||
StyledToggle(
|
||||
title = stringResource(R.string.noise_control).uppercase(),
|
||||
title = stringResource(R.string.noise_control),
|
||||
label = stringResource(R.string.noise_cancellation_single_airpod),
|
||||
description = stringResource(R.string.noise_cancellation_single_airpod_description),
|
||||
controlCommandIdentifier = AACPManager.Companion.ControlCommandIdentifiers.ONE_BUD_ANC_MODE,
|
||||
@@ -392,7 +394,7 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
||||
}
|
||||
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.tone_volume).uppercase(),
|
||||
label = stringResource(R.string.tone_volume),
|
||||
description = stringResource(R.string.tone_volume_description),
|
||||
mutableFloatState = toneVolumeValue,
|
||||
onValueChange = {
|
||||
@@ -405,6 +407,12 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
||||
independent = true
|
||||
)
|
||||
|
||||
StyledToggle(
|
||||
label = stringResource(R.string.volume_control),
|
||||
description = stringResource(R.string.volume_control_description),
|
||||
controlCommandIdentifier = AACPManager.Companion.ControlCommandIdentifiers.VOLUME_SWIPE_MODE,
|
||||
)
|
||||
|
||||
DropdownMenuComponent(
|
||||
label = stringResource(R.string.volume_swipe_speed),
|
||||
description = stringResource(R.string.volume_swipe_speed_description),
|
||||
@@ -425,10 +433,10 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
||||
|
||||
if (!hearingAidEnabled.value&& isSdpOffsetAvailable.value) {
|
||||
Text(
|
||||
text = stringResource(R.string.apply_eq_to).uppercase(),
|
||||
text = stringResource(R.string.apply_eq_to),
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = textColor.copy(alpha = 0.6f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
),
|
||||
@@ -437,12 +445,12 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(vertical = 0.dp)
|
||||
) {
|
||||
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 {
|
||||
mutableStateOf(
|
||||
if (darkModeLocal) Color(
|
||||
@@ -500,11 +508,11 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
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 {
|
||||
mutableStateOf(
|
||||
if (darkModeLocal) Color(
|
||||
@@ -565,7 +573,7 @@ fun AccessibilitySettingsScreen(navController: NavController) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
@@ -686,15 +694,18 @@ private fun DropdownMenuComponent(
|
||||
)
|
||||
.background(
|
||||
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(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 12.dp, end = 12.dp)
|
||||
.height(55.dp)
|
||||
.height(58.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures { offset ->
|
||||
val now = System.currentTimeMillis()
|
||||
@@ -766,7 +777,7 @@ private fun DropdownMenuComponent(
|
||||
color = textColor.copy(alpha = 0.6f),
|
||||
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 = selectedOption,
|
||||
fontSize = 16.sp,
|
||||
color = textColor.copy(alpha = 0.8f)
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
color = textColor.copy(alpha = 0.8f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
)
|
||||
)
|
||||
Icon(
|
||||
Icons.Default.KeyboardArrowDown,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(18.dp),
|
||||
tint = textColor.copy(alpha = 0.6f)
|
||||
Text(
|
||||
text = "",
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
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(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 8.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
.background(if (isSystemInDarkTheme()) Color(0xFF000000) else Color(0xFFF2F2F7))
|
||||
){
|
||||
Text(
|
||||
|
||||
@@ -36,6 +36,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -94,6 +96,7 @@ fun AdaptiveStrengthScreen(navController: NavController) {
|
||||
}
|
||||
}
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
|
||||
StyledScaffold(
|
||||
title = stringResource(R.string.customize_adaptive_audio),
|
||||
@@ -101,19 +104,21 @@ fun AdaptiveStrengthScreen(navController: NavController) {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
}
|
||||
) { spacerHeight ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.layerBackdrop(backdrop)
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(spacerHeight))
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.customize_adaptive_audio).uppercase(),
|
||||
label = stringResource(R.string.customize_adaptive_audio),
|
||||
mutableFloatState = sliderValue,
|
||||
onValueChange = {
|
||||
sliderValue.floatValue = it
|
||||
|
||||
@@ -68,6 +68,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||
import com.kyant.backdrop.drawBackdrop
|
||||
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.ConnectionSettings
|
||||
import me.kavishdevar.librepods.composables.MicrophoneSettings
|
||||
import me.kavishdevar.librepods.composables.NameField
|
||||
import me.kavishdevar.librepods.composables.NavigationButton
|
||||
import me.kavishdevar.librepods.composables.NoiseControlSettings
|
||||
import me.kavishdevar.librepods.composables.PressAndHoldSettings
|
||||
@@ -199,13 +199,15 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
||||
}
|
||||
}
|
||||
val darkMode = isSystemInDarkTheme()
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
StyledScaffold(
|
||||
title = deviceName.text,
|
||||
actionButtons = listOf {
|
||||
StyledIconButton(
|
||||
onClick = { navController.navigate("app_settings") },
|
||||
icon = "",
|
||||
darkMode = darkMode
|
||||
darkMode = darkMode,
|
||||
backdrop = backdrop
|
||||
)
|
||||
},
|
||||
snackbarHostState = snackbarHostState
|
||||
@@ -216,6 +218,7 @@ fun AirPodsSettingsScreen(dev: BluetoothDevice?, service: AirPodsService,
|
||||
.fillMaxSize()
|
||||
.hazeSource(hazeState)
|
||||
.padding(horizontal = 16.dp)
|
||||
.layerBackdrop(backdrop)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
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
|
||||
if (!bleOnlyMode) {
|
||||
NameField(
|
||||
NavigationButton(
|
||||
to = "rename",
|
||||
name = stringResource(R.string.name),
|
||||
value = deviceName.text,
|
||||
navController = navController
|
||||
currentState = deviceName.text,
|
||||
navController = navController,
|
||||
independent = true
|
||||
)
|
||||
}
|
||||
|
||||
if (!bleOnlyMode) {
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
NavigationButton(to = "hearing_aid", stringResource(R.string.hearing_aid), navController)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
NoiseControlSettings(service = service)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
PressAndHoldSettings(navController = navController)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
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
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
PressAndHoldSettings(navController = navController)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
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.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
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.material3.Card
|
||||
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.sp
|
||||
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.materials.ExperimentalHazeMaterialsApi
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -325,14 +324,15 @@ fun DebugScreen(navController: NavController) {
|
||||
}
|
||||
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
StyledScaffold(
|
||||
title = "Debug",
|
||||
navigationButton = {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
},
|
||||
actionButtons = listOf(
|
||||
@@ -344,6 +344,7 @@ fun DebugScreen(navController: NavController) {
|
||||
},
|
||||
icon = "",
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
}
|
||||
),
|
||||
@@ -353,6 +354,7 @@ fun DebugScreen(navController: NavController) {
|
||||
.fillMaxSize()
|
||||
.hazeSource(hazeState)
|
||||
.navigationBarsPadding()
|
||||
.layerBackdrop(backdrop)
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(spacerHeight))
|
||||
@@ -391,11 +393,13 @@ fun DebugScreen(navController: NavController) {
|
||||
)
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
imageVector = if (isSent) Icons.AutoMirrored.Filled.KeyboardArrowLeft else Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
||||
contentDescription = null,
|
||||
tint = if (isSent) Color.Green else Color.Red,
|
||||
modifier = Modifier.size(24.dp)
|
||||
Text(
|
||||
text = if (isSent) "" else "",
|
||||
style = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||
color = if (isSent) Color(0xFF4CD964) else Color(0xFFFF3B30)
|
||||
),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Column {
|
||||
|
||||
@@ -42,10 +42,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
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.sp
|
||||
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.materials.ExperimentalHazeMaterialsApi
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import me.kavishdevar.librepods.R
|
||||
import me.kavishdevar.librepods.composables.StyledButton
|
||||
import me.kavishdevar.librepods.composables.StyledIconButton
|
||||
import me.kavishdevar.librepods.composables.StyledScaffold
|
||||
import me.kavishdevar.librepods.composables.StyledToggle
|
||||
@@ -116,18 +116,19 @@ fun HeadTrackingScreen(navController: NavController) {
|
||||
}
|
||||
}
|
||||
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 scrollState = rememberScrollState()
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
StyledScaffold (
|
||||
title = stringResource(R.string.head_tracking),
|
||||
navigationButton = {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
},
|
||||
actionButtons = listOf(
|
||||
@@ -144,72 +145,95 @@ fun HeadTrackingScreen(navController: NavController) {
|
||||
}
|
||||
},
|
||||
icon = if (isActive) "" else "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
}
|
||||
),
|
||||
) { 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
|
||||
.fillMaxSize()
|
||||
.padding(top = 8.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
.verticalScroll(scrollState)
|
||||
.hazeSource(state = hazeState)
|
||||
.layerBackdrop(backdrop)
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(spacerHeight))
|
||||
val sharedPreferences =
|
||||
LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
Column (
|
||||
modifier = Modifier
|
||||
.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("") }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
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(
|
||||
label = "Head Gestures",
|
||||
sharedPreferences = sharedPreferences,
|
||||
sharedPreferenceKey = "head_gestures",
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
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)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
"Head Orientation",
|
||||
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)
|
||||
)
|
||||
HeadVisualization()
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
"Head Orientation",
|
||||
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)
|
||||
)
|
||||
HeadVisualization()
|
||||
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))
|
||||
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))
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Button (
|
||||
LaunchedEffect(gestureText) {
|
||||
if (gestureText.isNotEmpty()) {
|
||||
lastClickTime = System.currentTimeMillis()
|
||||
delay(3000)
|
||||
if (System.currentTimeMillis() - lastClickTime >= 3000) {
|
||||
shouldExplode = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
StyledButton(
|
||||
onClick = {
|
||||
gestureText = "Shake your head or nod!"
|
||||
coroutineScope.launch {
|
||||
@@ -217,13 +241,9 @@ fun HeadTrackingScreen(navController: NavController) {
|
||||
gestureText = if (accepted) "\"Yes\" gesture detected." else "\"No\" gesture detected."
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(55.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = backgroundColor
|
||||
),
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
backdrop = backdrop,
|
||||
modifier = Modifier.fillMaxWidth(0.75f),
|
||||
maxScale = 0.05f
|
||||
) {
|
||||
Text(
|
||||
"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(
|
||||
contentAlignment = Alignment.Center,
|
||||
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.unit.dp
|
||||
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.hazeSource
|
||||
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 aacpManager = remember { ServiceManager.getService()?.aacpManager }
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
StyledScaffold(
|
||||
title = stringResource(R.string.adjustments),
|
||||
navigationButton = {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
}
|
||||
) { spacerHeight ->
|
||||
@@ -92,6 +95,7 @@ fun HearingAidAdjustmentsScreen(@Suppress("unused") navController: NavController
|
||||
modifier = Modifier
|
||||
.hazeSource(hazeState)
|
||||
.fillMaxSize()
|
||||
.layerBackdrop(backdrop)
|
||||
.verticalScroll(verticalScrollState)
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
@@ -282,7 +286,7 @@ fun HearingAidAdjustmentsScreen(@Suppress("unused") navController: NavController
|
||||
}
|
||||
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.amplification).uppercase(),
|
||||
label = stringResource(R.string.amplification),
|
||||
valueRange = -1f..1f,
|
||||
mutableFloatState = amplificationSliderValue,
|
||||
onValueChange = {
|
||||
@@ -301,20 +305,20 @@ fun HearingAidAdjustmentsScreen(@Suppress("unused") navController: NavController
|
||||
)
|
||||
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.balance).uppercase(),
|
||||
label = stringResource(R.string.balance),
|
||||
valueRange = -1f..1f,
|
||||
mutableFloatState = balanceSliderValue,
|
||||
onValueChange = {
|
||||
balanceSliderValue.floatValue = it
|
||||
},
|
||||
snapPoints = listOf(0f),
|
||||
snapPoints = listOf(-1f, 0f, 1f),
|
||||
startLabel = stringResource(R.string.left),
|
||||
endLabel = stringResource(R.string.right),
|
||||
independent = true,
|
||||
)
|
||||
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.tone).uppercase(),
|
||||
label = stringResource(R.string.tone),
|
||||
valueRange = -1f..1f,
|
||||
mutableFloatState = toneSliderValue,
|
||||
onValueChange = {
|
||||
@@ -326,7 +330,7 @@ fun HearingAidAdjustmentsScreen(@Suppress("unused") navController: NavController
|
||||
)
|
||||
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.ambient_noise_reduction).uppercase(),
|
||||
label = stringResource(R.string.ambient_noise_reduction),
|
||||
valueRange = 0f..1f,
|
||||
mutableFloatState = ambientNoiseReductionSliderValue,
|
||||
onValueChange = {
|
||||
|
||||
@@ -20,15 +20,10 @@ package me.kavishdevar.librepods.screens
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
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.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
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.shape.RoundedCornerShape
|
||||
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.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
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.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.Font
|
||||
@@ -74,9 +62,9 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import me.kavishdevar.librepods.R
|
||||
import me.kavishdevar.librepods.composables.ConfirmationDialog
|
||||
import me.kavishdevar.librepods.composables.NavigationButton
|
||||
import me.kavishdevar.librepods.composables.StyledIconButton
|
||||
import me.kavishdevar.librepods.composables.StyledScaffold
|
||||
import me.kavishdevar.librepods.composables.StyledSwitch
|
||||
import me.kavishdevar.librepods.composables.StyledToggle
|
||||
import me.kavishdevar.librepods.services.ServiceManager
|
||||
import me.kavishdevar.librepods.utils.AACPManager
|
||||
@@ -117,7 +105,8 @@ fun HearingAidScreen(navController: NavController) {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
},
|
||||
actionButtons = emptyList(),
|
||||
@@ -129,7 +118,7 @@ fun HearingAidScreen(navController: NavController) {
|
||||
.hazeSource(hazeState)
|
||||
.fillMaxSize()
|
||||
.verticalScroll(verticalScrollState)
|
||||
.padding(16.dp),
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(spacerHeight))
|
||||
@@ -175,22 +164,22 @@ fun HearingAidScreen(navController: NavController) {
|
||||
}
|
||||
|
||||
fun onAdjustPhoneChange(value: Boolean) {
|
||||
adjustPhoneEnabled.value = value
|
||||
// TODO
|
||||
}
|
||||
|
||||
fun onAdjustMediaChange(value: Boolean) {
|
||||
adjustMediaEnabled.value = value
|
||||
// TODO
|
||||
}
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.hearing_aid).uppercase(),
|
||||
text = stringResource(R.string.hearing_aid),
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = textColor.copy(alpha = 0.6f),
|
||||
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)
|
||||
@@ -198,9 +187,9 @@ fun HearingAidScreen(navController: NavController) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
.clip(
|
||||
RoundedCornerShape(14.dp)
|
||||
RoundedCornerShape(28.dp)
|
||||
)
|
||||
) {
|
||||
StyledToggle(
|
||||
@@ -209,31 +198,17 @@ fun HearingAidScreen(navController: NavController) {
|
||||
independent = false
|
||||
)
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
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 = 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),
|
||||
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))
|
||||
|
||||
|
||||
StyledToggle(
|
||||
title = stringResource(R.string.media_assist).uppercase(),
|
||||
title = stringResource(R.string.media_assist),
|
||||
label = stringResource(R.string.media_assist),
|
||||
checkedState = mediaAssistEnabled,
|
||||
independent = true,
|
||||
@@ -260,99 +235,27 @@ fun HearingAidScreen(navController: NavController) {
|
||||
Column (
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
) {
|
||||
val isDarkThemeLocal = isSystemInDarkTheme()
|
||||
var backgroundColorAdjustMedia by remember { mutableStateOf(if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
||||
val animatedBackgroundColorAdjustMedia by animateColorAsState(targetValue = backgroundColorAdjustMedia, animationSpec = tween(durationMillis = 500))
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.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)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
StyledToggle(
|
||||
label = stringResource(R.string.adjust_media),
|
||||
checkedState = adjustMediaEnabled,
|
||||
onCheckedChange = { onAdjustMediaChange(it) },
|
||||
independent = false
|
||||
)
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
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)) }
|
||||
val animatedBackgroundColorAdjustPhone by animateColorAsState(targetValue = backgroundColorAdjustPhone, animationSpec = tween(durationMillis = 500))
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.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)
|
||||
},
|
||||
)
|
||||
}
|
||||
StyledToggle(
|
||||
label = stringResource(R.string.adjust_calls),
|
||||
checkedState = adjustPhoneEnabled,
|
||||
onCheckedChange = { onAdjustPhoneChange(it) },
|
||||
independent = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.edit
|
||||
import androidx.navigation.NavController
|
||||
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -151,6 +153,7 @@ fun Onboarding(navController: NavController, activityContext: Context) {
|
||||
isComplete = true
|
||||
}
|
||||
}
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
StyledScaffold(
|
||||
title = "Setting Up",
|
||||
actionButtons = listOf(
|
||||
@@ -160,7 +163,8 @@ fun Onboarding(navController: NavController, activityContext: Context) {
|
||||
showSkipDialog = true
|
||||
},
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -168,6 +172,7 @@ fun Onboarding(navController: NavController, activityContext: Context) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.layerBackdrop(backdrop)
|
||||
.padding(horizontal = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
|
||||
@@ -23,6 +23,7 @@ package me.kavishdevar.librepods.screens
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
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.wrapContentWidth
|
||||
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.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -50,11 +49,11 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.scale
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
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
|
||||
@@ -63,6 +62,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.edit
|
||||
import androidx.navigation.NavController
|
||||
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||
import me.kavishdevar.librepods.R
|
||||
import me.kavishdevar.librepods.composables.StyledIconButton
|
||||
@@ -76,20 +77,20 @@ import kotlin.io.encoding.ExperimentalEncodingApi
|
||||
@Composable
|
||||
fun RightDivider() {
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
modifier = Modifier
|
||||
.padding(start = 72.dp)
|
||||
.padding(start = 72.dp, end = 20.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RightDividerNoIcon() {
|
||||
HorizontalDivider(
|
||||
thickness = 1.5.dp,
|
||||
thickness = 1.dp,
|
||||
color = Color(0x40888888),
|
||||
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)
|
||||
Log.d("PressAndHoldSettingsScreen", "Long press action preference ($prefKey): $longPressActionPref")
|
||||
var longPressAction by remember { mutableStateOf(StemAction.valueOf(longPressActionPref ?: StemAction.CYCLE_NOISE_CONTROL_MODES.name)) }
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
StyledScaffold(
|
||||
title = name,
|
||||
navigationButton = {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
}
|
||||
) { spacerHeight ->
|
||||
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||
Column (
|
||||
modifier = Modifier
|
||||
.layerBackdrop(backdrop)
|
||||
.fillMaxSize()
|
||||
.padding(top = 8.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
@@ -138,11 +142,11 @@ fun LongPress(navController: NavController, name: String) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp)),
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp)),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
LongPressActionElement(
|
||||
name = "Noise Control",
|
||||
name = stringResource(R.string.noise_control),
|
||||
selected = longPressAction == StemAction.CYCLE_NOISE_CONTROL_MODES,
|
||||
onClick = {
|
||||
longPressAction = StemAction.CYCLE_NOISE_CONTROL_MODES
|
||||
@@ -153,7 +157,7 @@ fun LongPress(navController: NavController, name: String) {
|
||||
)
|
||||
RightDividerNoIcon()
|
||||
LongPressActionElement(
|
||||
name = "Digital Assistant",
|
||||
name = stringResource(R.string.digital_assistant),
|
||||
selected = longPressAction == StemAction.DIGITAL_ASSISTANT,
|
||||
onClick = {
|
||||
longPressAction = StemAction.DIGITAL_ASSISTANT
|
||||
@@ -165,23 +169,25 @@ fun LongPress(navController: NavController, name: String) {
|
||||
}
|
||||
|
||||
if (longPressAction == StemAction.CYCLE_NOISE_CONTROL_MODES) {
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
Text(
|
||||
text = "NOISE CONTROL",
|
||||
text = stringResource(R.string.noise_control),
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = textColor.copy(alpha = 0.6f),
|
||||
),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||
modifier = Modifier
|
||||
.padding(top = 32.dp, bottom = 4.dp)
|
||||
.padding(horizontal = 8.dp)
|
||||
.padding(horizontal = 18.dp)
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp)),
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp)),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
val offListeningModeValue = ServiceManager.getService()!!.aacpManager.controlCommandStatusList.find {
|
||||
@@ -189,28 +195,28 @@ fun LongPress(navController: NavController, name: String) {
|
||||
}?.value?.takeIf { it.isNotEmpty() }?.get(0)
|
||||
val offListeningMode = offListeningModeValue == 1.toByte()
|
||||
ListeningModeElement(
|
||||
name = "Off",
|
||||
name = stringResource(R.string.off),
|
||||
enabled = offListeningMode,
|
||||
resourceId = R.drawable.noise_cancellation,
|
||||
isFirst = true)
|
||||
if (offListeningMode) RightDivider()
|
||||
ListeningModeElement(
|
||||
name = "Transparency",
|
||||
name = stringResource(R.string.transparency),
|
||||
resourceId = R.drawable.transparency,
|
||||
isFirst = !offListeningMode)
|
||||
RightDivider()
|
||||
ListeningModeElement(
|
||||
name = "Adaptive",
|
||||
name = stringResource(R.string.adaptive),
|
||||
resourceId = R.drawable.adaptive)
|
||||
RightDivider()
|
||||
ListeningModeElement(
|
||||
name = "Noise Cancellation",
|
||||
name = stringResource(R.string.noise_cancellation),
|
||||
resourceId = R.drawable.noise_cancellation,
|
||||
isLast = true)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
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(
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
@@ -218,7 +224,7 @@ fun LongPress(navController: NavController, name: String) {
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
),
|
||||
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 {
|
||||
isFirst -> RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp)
|
||||
isLast -> RoundedCornerShape(bottomStart = 14.dp, bottomEnd = 14.dp)
|
||||
isFirst -> RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp)
|
||||
isLast -> RoundedCornerShape(bottomStart = 28.dp, bottomEnd = 28.dp)
|
||||
else -> RoundedCornerShape(0.dp)
|
||||
}
|
||||
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,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
@@ -384,24 +390,19 @@ fun ListeningModeElement(name: String, enabled: Boolean = true, resourceId: Int,
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||
)
|
||||
}
|
||||
Checkbox(
|
||||
checked = checked.value,
|
||||
onCheckedChange = { valueChanged() },
|
||||
colors = CheckboxDefaults.colors().copy(
|
||||
checkedCheckmarkColor = Color(0xFF007AFF),
|
||||
uncheckedCheckmarkColor = Color.Transparent,
|
||||
checkedBoxColor = Color.Transparent,
|
||||
uncheckedBoxColor = Color.Transparent,
|
||||
checkedBorderColor = Color.Transparent,
|
||||
uncheckedBorderColor = Color.Transparent,
|
||||
disabledBorderColor = Color.Transparent,
|
||||
disabledCheckedBoxColor = Color.Transparent,
|
||||
disabledUncheckedBoxColor = Color.Transparent,
|
||||
disabledUncheckedBorderColor = Color.Transparent
|
||||
|
||||
val floatAnimateState by animateFloatAsState(
|
||||
targetValue = if (checked.value) 1f else 0f,
|
||||
animationSpec = tween(durationMillis = 300)
|
||||
)
|
||||
Text(
|
||||
text = "",
|
||||
style = TextStyle(
|
||||
fontSize = 20.sp,
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||
color = Color(0xFF007AFF).copy(alpha = floatAnimateState),
|
||||
),
|
||||
modifier = Modifier
|
||||
.height(24.dp)
|
||||
.scale(1.5f),
|
||||
modifier = Modifier.padding(end = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -417,15 +418,15 @@ fun LongPressActionElement(
|
||||
) {
|
||||
val darkMode = isSystemInDarkTheme()
|
||||
val shape = when {
|
||||
isFirst -> RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp)
|
||||
isLast -> RoundedCornerShape(bottomStart = 14.dp, bottomEnd = 14.dp)
|
||||
isFirst -> RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp)
|
||||
isLast -> RoundedCornerShape(bottomStart = 28.dp, bottomEnd = 28.dp)
|
||||
else -> RoundedCornerShape(0.dp)
|
||||
}
|
||||
var backgroundColor by remember { mutableStateOf(if (darkMode) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) }
|
||||
val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500))
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(48.dp)
|
||||
.height(55.dp)
|
||||
.background(animatedBackgroundColor, shape)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
@@ -437,7 +438,7 @@ fun LongPressActionElement(
|
||||
}
|
||||
)
|
||||
}
|
||||
.padding(horizontal = 16.dp, vertical = 0.dp),
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
@@ -449,24 +450,18 @@ fun LongPressActionElement(
|
||||
.weight(1f)
|
||||
.padding(start = 4.dp)
|
||||
)
|
||||
Checkbox(
|
||||
checked = selected,
|
||||
onCheckedChange = { onClick() },
|
||||
colors = CheckboxDefaults.colors().copy(
|
||||
checkedCheckmarkColor = Color(0xFF007AFF),
|
||||
uncheckedCheckmarkColor = Color.Transparent,
|
||||
checkedBoxColor = Color.Transparent,
|
||||
uncheckedBoxColor = Color.Transparent,
|
||||
checkedBorderColor = Color.Transparent,
|
||||
uncheckedBorderColor = Color.Transparent,
|
||||
disabledBorderColor = Color.Transparent,
|
||||
disabledCheckedBoxColor = Color.Transparent,
|
||||
disabledUncheckedBoxColor = Color.Transparent,
|
||||
disabledUncheckedBorderColor = Color.Transparent
|
||||
val floatAnimateState by animateFloatAsState(
|
||||
targetValue = if (selected) 1f else 0f,
|
||||
animationSpec = tween(durationMillis = 300)
|
||||
)
|
||||
Text(
|
||||
text = "",
|
||||
style = TextStyle(
|
||||
fontSize = 20.sp,
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||
color = Color(0xFF007AFF).copy(alpha = floatAnimateState)
|
||||
),
|
||||
modifier = Modifier
|
||||
.height(24.dp)
|
||||
.scale(1.5f),
|
||||
modifier = Modifier.padding(end = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,9 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
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.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
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.text.TextRange
|
||||
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.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.edit
|
||||
import androidx.navigation.NavController
|
||||
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||
import me.kavishdevar.librepods.R
|
||||
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))
|
||||
}
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
|
||||
StyledScaffold(
|
||||
title = stringResource(R.string.name),
|
||||
navigationButton = {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
},
|
||||
) { spacerHeight ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.layerBackdrop(backdrop)
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(spacerHeight))
|
||||
@@ -105,10 +111,10 @@ fun RenameScreen(navController: NavController) {
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(55.dp)
|
||||
.height(58.dp)
|
||||
.background(
|
||||
backgroundColor,
|
||||
RoundedCornerShape(14.dp)
|
||||
RoundedCornerShape(28.dp)
|
||||
)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
) {
|
||||
@@ -120,8 +126,9 @@ fun RenameScreen(navController: NavController) {
|
||||
ServiceManager.getService()?.setName(it.text)
|
||||
},
|
||||
textStyle = TextStyle(
|
||||
color = textColor,
|
||||
fontSize = 16.sp,
|
||||
color = textColor,
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
),
|
||||
singleLine = true,
|
||||
cursorBrush = SolidColor(cursorColor),
|
||||
@@ -138,14 +145,15 @@ fun RenameScreen(navController: NavController) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
name.value = TextFieldValue("")
|
||||
sharedPreferences.edit { putString("name", "") }
|
||||
ServiceManager.getService()?.setName("")
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Clear,
|
||||
contentDescription = "Clear",
|
||||
tint = if (isDarkTheme) Color.White else Color.Black
|
||||
Text(
|
||||
text = "",
|
||||
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.6f)
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,8 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
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.materials.ExperimentalHazeMaterialsApi
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -95,19 +97,23 @@ fun TransparencySettingsScreen(navController: NavController) {
|
||||
val activeTrackColor = if (isDarkTheme) Color(0xFF007AFF) else Color(0xFF3C6DF5)
|
||||
val thumbColor = if (isDarkTheme) Color(0xFFFFFFFF) else Color(0xFFFFFFFF)
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
|
||||
StyledScaffold(
|
||||
title = stringResource(R.string.customize_transparency_mode),
|
||||
navigationButton = {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
}
|
||||
){ spacerHeight, hazeState ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.hazeSource(hazeState)
|
||||
.layerBackdrop(backdrop)
|
||||
.fillMaxSize()
|
||||
.verticalScroll(verticalScrollState)
|
||||
.padding(horizontal = 16.dp),
|
||||
@@ -154,19 +160,15 @@ fun TransparencySettingsScreen(navController: NavController) {
|
||||
object : (ByteArray) -> Unit {
|
||||
override fun invoke(value: ByteArray) {
|
||||
val parsed = parseTransparencySettingsResponse(value)
|
||||
if (parsed != null) {
|
||||
enabled.value = parsed.enabled
|
||||
amplificationSliderValue.floatValue = parsed.netAmplification
|
||||
balanceSliderValue.floatValue = parsed.balance
|
||||
toneSliderValue.floatValue = parsed.leftTone
|
||||
ambientNoiseReductionSliderValue.floatValue =
|
||||
parsed.leftAmbientNoiseReduction
|
||||
conversationBoostEnabled.value = parsed.leftConversationBoost
|
||||
eq.value = parsed.leftEQ.copyOf()
|
||||
Log.d(TAG, "Updated transparency settings from notification")
|
||||
} else {
|
||||
Log.w(TAG, "Failed to parse transparency settings from notification")
|
||||
}
|
||||
enabled.value = parsed.enabled
|
||||
amplificationSliderValue.floatValue = parsed.netAmplification
|
||||
balanceSliderValue.floatValue = parsed.balance
|
||||
toneSliderValue.floatValue = parsed.leftTone
|
||||
ambientNoiseReductionSliderValue.floatValue =
|
||||
parsed.leftAmbientNoiseReduction
|
||||
conversationBoostEnabled.value = parsed.leftConversationBoost
|
||||
eq.value = parsed.leftEQ.copyOf()
|
||||
Log.d(TAG, "Updated transparency settings from notification")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,12 +253,7 @@ fun TransparencySettingsScreen(navController: NavController) {
|
||||
try {
|
||||
val data = attManager.read(ATTHandles.TRANSPARENCY)
|
||||
parsedSettings = parseTransparencySettingsResponse(data = data)
|
||||
if (parsedSettings != null) {
|
||||
Log.d(TAG, "Parsed settings on attempt $attempt")
|
||||
break
|
||||
} else {
|
||||
Log.d(TAG, "Parsing returned null on attempt $attempt")
|
||||
}
|
||||
Log.d(TAG, "Parsed settings on attempt $attempt")
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Read attempt $attempt failed: ${e.message}")
|
||||
}
|
||||
@@ -297,7 +294,7 @@ fun TransparencySettingsScreen(navController: NavController) {
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.amplification).uppercase(),
|
||||
label = stringResource(R.string.amplification),
|
||||
valueRange = -1f..1f,
|
||||
mutableFloatState = amplificationSliderValue,
|
||||
onValueChange = {
|
||||
@@ -309,20 +306,20 @@ fun TransparencySettingsScreen(navController: NavController) {
|
||||
)
|
||||
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.balance).uppercase(),
|
||||
label = stringResource(R.string.balance),
|
||||
valueRange = -1f..1f,
|
||||
mutableFloatState = balanceSliderValue,
|
||||
onValueChange = {
|
||||
balanceSliderValue.floatValue = it
|
||||
},
|
||||
snapPoints = listOf(0f),
|
||||
snapPoints = listOf(-1f, 0f, 1f),
|
||||
startLabel = stringResource(R.string.left),
|
||||
endLabel = stringResource(R.string.right),
|
||||
independent = true,
|
||||
)
|
||||
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.tone).uppercase(),
|
||||
label = stringResource(R.string.tone),
|
||||
valueRange = -1f..1f,
|
||||
mutableFloatState = toneSliderValue,
|
||||
onValueChange = {
|
||||
@@ -334,7 +331,7 @@ fun TransparencySettingsScreen(navController: NavController) {
|
||||
)
|
||||
|
||||
StyledSlider(
|
||||
label = stringResource(R.string.ambient_noise_reduction).uppercase(),
|
||||
label = stringResource(R.string.ambient_noise_reduction),
|
||||
valueRange = 0f..1f,
|
||||
mutableFloatState = ambientNoiseReductionSliderValue,
|
||||
onValueChange = {
|
||||
@@ -356,20 +353,20 @@ fun TransparencySettingsScreen(navController: NavController) {
|
||||
// Only show transparency mode EQ section if SDP offset is available
|
||||
if (isSdpOffsetAvailable.value) {
|
||||
Text(
|
||||
text = stringResource(R.string.equalizer).uppercase(),
|
||||
text = stringResource(R.string.equalizer),
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = textColor.copy(alpha = 0.6f),
|
||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||
),
|
||||
modifier = Modifier.padding(8.dp, bottom = 2.dp)
|
||||
modifier = Modifier.padding(16.dp, bottom = 4.dp)
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor, RoundedCornerShape(14.dp))
|
||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||
.padding(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.SpaceBetween
|
||||
|
||||
@@ -85,6 +85,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.FileProvider
|
||||
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.materials.ExperimentalHazeMaterialsApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -208,6 +210,8 @@ fun TroubleshootingScreen(navController: NavController) {
|
||||
showBottomSheet = true
|
||||
}
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
@@ -217,28 +221,30 @@ fun TroubleshootingScreen(navController: NavController) {
|
||||
StyledIconButton(
|
||||
onClick = { navController.popBackStack() },
|
||||
icon = "",
|
||||
darkMode = isDarkTheme
|
||||
darkMode = isDarkTheme,
|
||||
backdrop = backdrop
|
||||
)
|
||||
}
|
||||
){ spacerHeight, hazeState ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(scrollState)
|
||||
.layerBackdrop(backdrop)
|
||||
.hazeSource(state = hazeState)
|
||||
.verticalScroll(scrollState)
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(spacerHeight))
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.saved_logs).uppercase(),
|
||||
text = stringResource(R.string.saved_logs),
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = textColor.copy(alpha = 0.6f),
|
||||
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))
|
||||
@@ -249,7 +255,7 @@ fun TroubleshootingScreen(navController: NavController) {
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
backgroundColor,
|
||||
RoundedCornerShape(14.dp)
|
||||
RoundedCornerShape(28.dp)
|
||||
)
|
||||
.padding(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
@@ -266,7 +272,7 @@ fun TroubleshootingScreen(navController: NavController) {
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
backgroundColor,
|
||||
RoundedCornerShape(14.dp)
|
||||
RoundedCornerShape(28.dp)
|
||||
)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
) {
|
||||
@@ -372,14 +378,14 @@ fun TroubleshootingScreen(navController: NavController) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Text(
|
||||
text = "TROUBLESHOOTING STEPS".uppercase(),
|
||||
text = "TROUBLESHOOTING STEPS",
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Light,
|
||||
color = textColor.copy(alpha = 0.6f),
|
||||
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))
|
||||
@@ -389,7 +395,7 @@ fun TroubleshootingScreen(navController: NavController) {
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
backgroundColor,
|
||||
RoundedCornerShape(14.dp)
|
||||
RoundedCornerShape(28.dp)
|
||||
)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
<string name="case_alt">Case</string>
|
||||
<string name="test">Test</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="transparency">Transparency</string>
|
||||
<string name="adaptive">Adaptive</string>
|
||||
<string name="noise_cancellation">Noise Cancellation</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="left">Left</string>
|
||||
<string name="right">Right</string>
|
||||
@@ -110,7 +111,7 @@
|
||||
<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_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_description">To prevent unintended volume adjustments, select preferred wait time between swipes.</string>
|
||||
<string name="equalizer">Equalizer</string>
|
||||
@@ -133,7 +134,7 @@
|
||||
<string name="ambient_noise_reduction">Ambient Noise Reduction</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="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_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>
|
||||
@@ -174,4 +175,5 @@
|
||||
<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="found_offset_restart_bluetooth">Found offset please restart the Bluetooth process</string>
|
||||
<string name="digital_assistant">Digital Assistant</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user