diff --git a/app/src/main/java/com/eipsaferoad/owl/components/Button.kt b/app/src/main/java/com/eipsaferoad/owl/components/Button.kt index e58de08..8fd0d95 100644 --- a/app/src/main/java/com/eipsaferoad/owl/components/Button.kt +++ b/app/src/main/java/com/eipsaferoad/owl/components/Button.kt @@ -38,7 +38,7 @@ fun Button(type: ButtonTypeEnum, content: @Composable () -> Unit, action: () -> Column( modifier = Modifier .fillMaxSize() - .clip(shape = RoundedCornerShape(20.dp)) + .clip(shape = RoundedCornerShape(100.dp)) .background(backgroundColor) .clickable { action() }, verticalArrangement = Arrangement.Center, diff --git a/app/src/main/java/com/eipsaferoad/owl/components/Draggeable.kt b/app/src/main/java/com/eipsaferoad/owl/components/Draggeable.kt index e292b89..a93771f 100644 --- a/app/src/main/java/com/eipsaferoad/owl/components/Draggeable.kt +++ b/app/src/main/java/com/eipsaferoad/owl/components/Draggeable.kt @@ -8,9 +8,9 @@ import androidx.compose.ui.Modifier import com.eipsaferoad.owl.models.Alarm fun Modifier.handleDraggableModifier( - lastPosX: Float, - vibrationVal: Float, - nbrPixelToMove: Int, + lastPosX: MutableState, + vibrationVal: MutableState, + nbrPixelToMove: MutableState, alarms: MutableState, dragLeft: (value: Float) -> Unit, dragRight: (value: Float) -> Unit, @@ -19,12 +19,12 @@ fun Modifier.handleDraggableModifier( return this.pointerInput(Unit) { detectDragGestures { change, dragAmount -> change.consume() - if (lastPosX == 0.0f) { + if (lastPosX.value == 0.0f) { init(change.position.x) } - if (change.previousPosition.x < change.position.x && abs(lastPosX - change.position.x) > nbrPixelToMove && vibrationVal < alarms.value.vibration.max.toFloat()) { + if (change.previousPosition.x < change.position.x && abs(lastPosX.value - change.position.x) > nbrPixelToMove.value && vibrationVal.value < alarms.value.vibration.max.toFloat()) { dragRight(change.position.x) - } else if (change.previousPosition.x > change.position.x && abs(lastPosX - change.position.x) > nbrPixelToMove && vibrationVal > alarms.value.vibration.min) { + } else if (change.previousPosition.x > change.position.x && abs(lastPosX.value - change.position.x) > nbrPixelToMove.value && vibrationVal.value > alarms.value.vibration.min) { dragLeft(change.position.x) } println(vibrationVal) diff --git a/app/src/main/java/com/eipsaferoad/owl/components/ToggleSwitch.kt b/app/src/main/java/com/eipsaferoad/owl/components/ToggleSwitch.kt index a31b280..98f3ecd 100644 --- a/app/src/main/java/com/eipsaferoad/owl/components/ToggleSwitch.kt +++ b/app/src/main/java/com/eipsaferoad/owl/components/ToggleSwitch.kt @@ -12,16 +12,18 @@ import androidx.compose.ui.unit.dp import androidx.wear.compose.material.Switch import androidx.wear.compose.material.SwitchDefaults import com.eipsaferoad.owl.presentation.theme.md_theme_dark_tertiary +import com.eipsaferoad.owl.presentation.theme.md_theme_light_primary +import com.eipsaferoad.owl.presentation.theme.md_theme_light_secondary import com.eipsaferoad.owl.presentation.theme.md_theme_light_surface @Composable fun ToggleSwitch(isActivate: Boolean, action: (it: Boolean) -> Unit) { Switch( colors = SwitchDefaults.colors( - checkedThumbColor = md_theme_light_surface, - checkedTrackColor = md_theme_light_surface, - uncheckedThumbColor = md_theme_light_surface, - uncheckedTrackColor = md_theme_dark_tertiary + checkedThumbColor = md_theme_light_primary, + checkedTrackColor = md_theme_light_secondary, + uncheckedThumbColor = md_theme_light_primary, + uncheckedTrackColor = md_theme_light_secondary ), checked = isActivate, onCheckedChange = { diff --git a/app/src/main/java/com/eipsaferoad/owl/presentation/home/Home.kt b/app/src/main/java/com/eipsaferoad/owl/presentation/home/Home.kt index 9f26a7d..3f50cf7 100644 --- a/app/src/main/java/com/eipsaferoad/owl/presentation/home/Home.kt +++ b/app/src/main/java/com/eipsaferoad/owl/presentation/home/Home.kt @@ -8,8 +8,10 @@ import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.infiniteRepeatable import androidx.compose.animation.core.rememberInfiniteTransition import androidx.compose.animation.core.tween +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.gestures.detectDragGestures import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -19,6 +21,8 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Clear @@ -26,9 +30,11 @@ import androidx.compose.material.icons.rounded.Favorite import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface 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.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush @@ -58,6 +64,11 @@ import com.eipsaferoad.owl.utils.LocalStorage import com.eipsaferoad.owl.utils.getVibrationEffects import com.eipsaferoad.owl.utils.soundPlayer import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalWindowInfo +import androidx.compose.ui.res.painterResource @Composable fun Home(currentHeartRate: MutableState, context: Context, navController: NavHostController, alarms: MutableState, mVibrator: Vibrator) { @@ -70,16 +81,51 @@ fun Home(currentHeartRate: MutableState, context: Context, navController @Composable fun NoAlarm(currentHeartRate: String, context: Context, navController: NavHostController) { + val lazyListState = rememberLazyListState( + initialFirstVisibleItemIndex = 1 + ) + Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { LazyColumn( + state = lazyListState, modifier = Modifier.height(200.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { + item { + Column( + modifier = Modifier.padding(top = 80.dp, start = 10.dp, end = 10.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Button( + type = ButtonTypeEnum.REDIRECTION, + content = { + Text( + fontSize = 17.sp, + text = "DISCONNECTION", + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(vertical = 10.dp) + ) + }, + action = { + LocalStorage.deleteData(context, EnvEnum.EMAIL.value) + LocalStorage.deleteData(context, EnvEnum.PASSWORD.value) + navController.navigate(PagesEnum.LOGIN.value) + } + ) + Image( + painter = painterResource(id = R.drawable.logout), + contentDescription = "logout", + modifier = Modifier + .size(30.dp) + .padding(top = 10.dp) + ) + } + } item { Column( modifier = Modifier.padding(bottom = 100.dp, top = 70.dp), @@ -98,47 +144,29 @@ fun NoAlarm(currentHeartRate: String, context: Context, navController: NavHostCo } } item { - Buttons(context = context, navController = navController) + Column( + modifier = Modifier.padding(bottom = 60.dp, start = 10.dp, end = 10.dp) + ) { + Button( + type = ButtonTypeEnum.PRIMARY, + content = { + Text( + fontSize = 30.sp, + text = "ALARM", + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(vertical = 15.dp) + ) + }, + action = { + navController.navigate(PagesEnum.SETTINGS.value) + } + ) + } } } } } -@Composable -fun Buttons(context: Context, navController: NavHostController) { - Column( - modifier = Modifier.padding(bottom = 40.dp), - verticalArrangement = Arrangement.spacedBy(10.dp) - ) { - Button( - type = ButtonTypeEnum.PRIMARY, - content = { - Text( - fontSize = 30.sp, - text = "ALARM" - ) - }, - action = { - navController.navigate(PagesEnum.SETTINGS.value) - } - ) - Button( - type = ButtonTypeEnum.REDIRECTION, - content = { - Text( - fontSize = 17.sp, - text = "DISCONNECTION", - ) - }, - action = { - LocalStorage.deleteData(context, EnvEnum.EMAIL.value) - LocalStorage.deleteData(context, EnvEnum.PASSWORD.value) - navController.navigate(PagesEnum.LOGIN.value) - } - ) - } -} - @Composable fun MultiColorBorderCircularColumn( borderColors: List, @@ -301,15 +329,6 @@ fun PreviewHome() { }*/ } -@Composable -@Preview -fun PreviewButtons() { - val navController = rememberSwipeDismissableNavController() - OwlTheme { - Buttons(LocalContext.current, navController) - } -} - @Composable @Preview(device = Devices.WEAR_OS_LARGE_ROUND, showSystemUi = true) fun PreviewAlarm() { diff --git a/app/src/main/java/com/eipsaferoad/owl/presentation/settings/Settings.kt b/app/src/main/java/com/eipsaferoad/owl/presentation/settings/Settings.kt index 1da60f4..95bce58 100644 --- a/app/src/main/java/com/eipsaferoad/owl/presentation/settings/Settings.kt +++ b/app/src/main/java/com/eipsaferoad/owl/presentation/settings/Settings.kt @@ -4,6 +4,7 @@ import android.content.Context import android.os.Build import android.os.Vibrator import androidx.annotation.RequiresApi +import androidx.compose.animation.core.animateDpAsState import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectDragGestures @@ -15,6 +16,7 @@ import androidx.compose.foundation.layout.fillMaxSize 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.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape @@ -30,18 +32,23 @@ 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.painterResource import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.wear.compose.material.Button import androidx.wear.compose.material.ButtonDefaults +import androidx.wear.compose.material.Icon import androidx.wear.compose.material.Text import com.eipsaferoad.owl.R import com.eipsaferoad.owl.api.Request import com.eipsaferoad.owl.components.ToggleSwitch import com.eipsaferoad.owl.components.handleDraggableModifier import com.eipsaferoad.owl.models.Alarm +import com.eipsaferoad.owl.presentation.theme.md_theme_light_onSurfaceVariant import com.eipsaferoad.owl.utils.EnvEnum import com.eipsaferoad.owl.utils.LocalStorage import com.eipsaferoad.owl.utils.getVibrationEffects @@ -77,7 +84,7 @@ fun saveOnServer(apiUrl: String, accessToken: String?, alarms: Alarm) { put("isVibrationActivate", alarms.vibration.isActivate) put("vibrationLevel", alarms.vibration.actual.toInt()) put("isSoundActivate", alarms.sound.isActivate) - put("soundLevel", alarms.sound.actual) + put("soundLevel", alarms.sound.actual.toInt()) put("music", alarms.music) put("iconId", alarms.iconId) }.toString() @@ -85,7 +92,7 @@ fun saveOnServer(apiUrl: String, accessToken: String?, alarms: Alarm) { Request.makeRequest( "$apiUrl/api/alarmPreferences", Request.Companion.REQUEST_TYPE.PUT, - {}, + { println("data save on server") }, headers, jsonBody, ) @@ -106,7 +113,7 @@ fun AlarmButton(context: Context, alarms: MutableState, apiUrl: String, a .width(200.dp) .height(40.dp), shape = RoundedCornerShape(10), - colors = ButtonDefaults.buttonColors(backgroundColor = MaterialTheme.colorScheme.primary), + colors = ButtonDefaults.buttonColors(backgroundColor = Color.Transparent), onClick = { alarms.value.isAlarmActivate = !alarms.value.isAlarmActivate } ) { Row( @@ -128,15 +135,16 @@ fun AlarmButton(context: Context, alarms: MutableState, apiUrl: String, a } } -@OptIn(ExperimentalFoundationApi::class) @Composable fun VibrationButton(context: Context, alarms: MutableState, mVibrator: Vibrator, apiUrl: String, accessToken: String?) { var isVibrationSelected by remember { mutableStateOf(false) } var isVibrationActivate by remember { mutableStateOf(alarms.value.vibration.isActivate) } var vibrationVal by remember { mutableStateOf(alarms.value.vibration.actual) } var lastPosX by remember { mutableStateOf(0.0f) } - val nbrPixelToMove = 70 - + val nbrPixelToMove by remember { mutableStateOf(70) } + var heightBar by remember { mutableStateOf(10.dp) } + val animatedHeightBar by animateDpAsState(targetValue = heightBar) + DisposableEffect(isVibrationActivate, vibrationVal) { onDispose { var data = if (isVibrationActivate) "1" else "0" @@ -150,7 +158,7 @@ fun VibrationButton(context: Context, alarms: MutableState, mVibrator: Vi .width(200.dp) .height(if (isVibrationSelected) 80.dp else 40.dp), shape = RoundedCornerShape(10), - colors = ButtonDefaults.buttonColors(backgroundColor = MaterialTheme.colorScheme.primary), + colors = ButtonDefaults.buttonColors(backgroundColor = md_theme_light_onSurfaceVariant), onClick = { isVibrationSelected = !isVibrationSelected } @@ -158,7 +166,7 @@ fun VibrationButton(context: Context, alarms: MutableState, mVibrator: Vi Column( modifier = Modifier .fillMaxSize() - .padding(top = if (isVibrationSelected) 0.dp else 10.dp, bottom = 10.dp), + .padding(top = 10.dp, bottom = 10.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.SpaceAround ) { @@ -179,19 +187,23 @@ fun VibrationButton(context: Context, alarms: MutableState, mVibrator: Vi saveOnServer(apiUrl, accessToken, alarms.value) } ) + } else { + Icon(painter = painterResource(id = R.drawable.vibration), contentDescription = "") } } if (isVibrationSelected) { Row( modifier = Modifier - .fillMaxWidth() - .padding(start = 10.dp, end = 10.dp), + .width(180.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Text( text = "-", - modifier = Modifier.clickable { + fontSize = 30.sp, + modifier = Modifier + .padding(end = 10.dp) + .clickable { alarms.value.vibration.updateAlarm(false) saveOnServer(apiUrl, accessToken, alarms.value) if (vibrationVal > alarms.value.vibration.min.toFloat()) { @@ -202,40 +214,51 @@ fun VibrationButton(context: Context, alarms: MutableState, mVibrator: Vi ) Box( modifier = Modifier - .width(150.dp) - .height(5.dp) + .width(130.dp) + .height(animatedHeightBar) .clip(RoundedCornerShape(8.dp)) ) { LinearProgressIndicator( progress = vibrationVal / (alarms.value.vibration.max - alarms.value.vibration.min), modifier = Modifier .pointerInput(Unit) { - detectDragGestures { change, dragAmount -> + detectDragGestures( + onDragEnd = {heightBar = 10.dp} + ) { change, dragAmount -> change.consume() + heightBar = 20.dp if (lastPosX == 0.0f) { lastPosX = change.position.x } - if (change.previousPosition.x < change.position.x && abs(lastPosX - change.position.x) > nbrPixelToMove && vibrationVal < alarms.value.vibration.max.toFloat()) { + if (change.previousPosition.x < change.position.x && abs( + lastPosX - change.position.x + ) > nbrPixelToMove && vibrationVal < alarms.value.vibration.max.toFloat() + ) { println("up") vibrationVal += 1f lastPosX = change.position.x - /*mVibrator.vibrate(getVibrationEffects()[alarms.value.vibration.actual.toInt()])*/ - } else if (change.previousPosition.x > change.position.x && abs(lastPosX - change.position.x) > nbrPixelToMove && vibrationVal > alarms.value.vibration.min.toFloat()) { + mVibrator.vibrate(getVibrationEffects()[alarms.value.vibration.actual.toInt()]) + saveOnServer(apiUrl, accessToken, alarms.value) + } else if (change.previousPosition.x > change.position.x && abs(lastPosX - change.position.x) > nbrPixelToMove && vibrationVal > alarms.value.vibration.min.toFloat() + ) { println("down") vibrationVal -= 1f lastPosX = change.position.x - /*mVibrator.vibrate(getVibrationEffects()[alarms.value.vibration.actual.toInt()])*/ + mVibrator.vibrate(getVibrationEffects()[alarms.value.vibration.actual.toInt()]) + saveOnServer(apiUrl, accessToken, alarms.value) } println(vibrationVal) } } - .height(5.dp), + .height(animatedHeightBar), color = MaterialTheme.colorScheme.secondary ) } Text( text = "+", + fontSize = 30.sp, modifier = Modifier + .padding(start = 5.dp) .clickable { alarms.value.vibration.updateAlarm() saveOnServer(apiUrl, accessToken, alarms.value) @@ -257,6 +280,10 @@ fun SoundButton(alarms: MutableState, context: Context, apiUrl: String, a var soundVal by remember { mutableStateOf(alarms.value.sound.actual) } var isVibrationSelected by remember { mutableStateOf(false) } var isSoundSelected by remember { mutableStateOf(false) } + var lastPosX by remember { mutableStateOf(0.0f) } + val nbrPixelToMove by remember { mutableStateOf(40) } + var heightBar by remember { mutableStateOf(10.dp) } + val animatedHeightBar by animateDpAsState(targetValue = heightBar) DisposableEffect(isSoundActivate, soundVal) { onDispose { @@ -271,7 +298,7 @@ fun SoundButton(alarms: MutableState, context: Context, apiUrl: String, a .width(200.dp) .height(if (isSoundSelected) 80.dp else 40.dp), shape = RoundedCornerShape(10), - colors = ButtonDefaults.buttonColors(backgroundColor = MaterialTheme.colorScheme.primary), + colors = ButtonDefaults.buttonColors(backgroundColor = md_theme_light_onSurfaceVariant), onClick = { isSoundSelected = !isSoundSelected if (isVibrationSelected) { @@ -282,7 +309,7 @@ fun SoundButton(alarms: MutableState, context: Context, apiUrl: String, a Column( modifier = Modifier .fillMaxSize() - .padding(top = if (isSoundSelected) 0.dp else 10.dp, bottom = 10.dp), + .padding(top = 10.dp, bottom = 10.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.SpaceAround ) { @@ -303,19 +330,23 @@ fun SoundButton(alarms: MutableState, context: Context, apiUrl: String, a saveOnServer(apiUrl, accessToken, alarms.value) } ) + } else { + Icon(painter = painterResource(id = R.drawable.sound), contentDescription = "") } } if (isSoundSelected) { Row( modifier = Modifier - .fillMaxWidth() - .padding(start = 10.dp, end = 10.dp), + .width(180.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Text( text = "-", - modifier = Modifier.clickable { + fontSize = 30.sp, + modifier = Modifier + .padding(end = 10.dp) + .clickable { alarms.value.sound.updateAlarm(false) saveOnServer(apiUrl, accessToken, alarms.value) if (soundVal > alarms.value.sound.min) { @@ -326,20 +357,56 @@ fun SoundButton(alarms: MutableState, context: Context, apiUrl: String, a ) Box( modifier = Modifier - .width(150.dp) - .height(5.dp) + .width(130.dp) + .height(animatedHeightBar) .clip(RoundedCornerShape(8.dp)) ) { LinearProgressIndicator( progress = soundVal / (alarms.value.sound.max - alarms.value.sound.min), modifier = Modifier - .height(5.dp), + .pointerInput(Unit) { + detectDragGestures( + onDragEnd = {heightBar = 10.dp} + ) { change, dragAmount -> + change.consume() + heightBar = 20.dp + if (lastPosX == 0.0f) { + lastPosX = change.position.x + } + if (change.previousPosition.x < change.position.x && abs(lastPosX - change.position.x) > nbrPixelToMove && soundVal < alarms.value.sound.max.toFloat() + ) { + soundVal += 0.2f + lastPosX = change.position.x + soundPlayer( + context, + soundVal, + fileId = R.raw.alarm_test + ) + saveOnServer(apiUrl, accessToken, alarms.value) + } else if (change.previousPosition.x > change.position.x && abs( + lastPosX - change.position.x + ) > nbrPixelToMove && soundVal > alarms.value.sound.min.toFloat() + ) { + soundVal -= 0.2f + lastPosX = change.position.x + soundPlayer( + context, + soundVal, + fileId = R.raw.alarm_test + ) + saveOnServer(apiUrl, accessToken, alarms.value) + } + } + } + .height(animatedHeightBar), color = MaterialTheme.colorScheme.secondary ) } Text( text = "+", + fontSize = 30.sp, modifier = Modifier + .padding(start = 10.dp) .clickable { alarms.value.sound.updateAlarm() saveOnServer(apiUrl, accessToken, alarms.value) diff --git a/app/src/main/res/drawable/logout.png b/app/src/main/res/drawable/logout.png new file mode 100644 index 0000000..1443cdf Binary files /dev/null and b/app/src/main/res/drawable/logout.png differ diff --git a/app/src/main/res/drawable/sound.png b/app/src/main/res/drawable/sound.png new file mode 100644 index 0000000..8afe813 Binary files /dev/null and b/app/src/main/res/drawable/sound.png differ diff --git a/app/src/main/res/drawable/vibration.png b/app/src/main/res/drawable/vibration.png new file mode 100644 index 0000000..176e4bd Binary files /dev/null and b/app/src/main/res/drawable/vibration.png differ