Skip to content

Commit

Permalink
Merge pull request #17 from YuanLiou/feature/insert_value_p3
Browse files Browse the repository at this point in the history
Insert Value Patch 03
  • Loading branch information
YuanLiou authored Jul 16, 2023
2 parents ef18b79 + fa9c864 commit feebf1a
Show file tree
Hide file tree
Showing 13 changed files with 482 additions and 43 deletions.
51 changes: 50 additions & 1 deletion wear/src/main/java/com/rayliu/gymnote/wearos/MainNavGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,23 @@ import androidx.wear.compose.foundation.lazy.ScalingLazyListState
import androidx.wear.compose.navigation.composable
import com.rayliu.gymnote.wearos.addrecord.AddRecordScreen
import com.rayliu.gymnote.wearos.addrecord.AddRecordViewModel
import com.rayliu.gymnote.wearos.addrecord.recordinput.DEFAULT_TIME_RECORD
import com.rayliu.gymnote.wearos.categorylist.CategoryListScreen
import com.rayliu.gymnote.wearos.categorylist.CategoryListViewModel
import com.rayliu.gymnote.wearos.navigation.CATEGORY_ID_NAV_ARGUMENT
import com.rayliu.gymnote.wearos.navigation.DestinationScrollType
import com.rayliu.gymnote.wearos.navigation.SCROLL_TYPE_NAV_ARGUMENT
import com.rayliu.gymnote.wearos.navigation.Screen
import com.rayliu.gymnote.wearos.navigation.TIME_PICKER_NAV_ARGUMENT
import com.rayliu.gymnote.wearos.navigation.TIME_PICKER_RESULT_NAV_ARGUMENT
import com.rayliu.gymnote.wearos.navigation.WORKOUT_ID_NAV_ARGUMENT
import com.rayliu.gymnote.wearos.timepicker.TimePickerScreen
import com.rayliu.gymnote.wearos.workout.WorkoutScreen
import com.rayliu.gymnote.wearos.workout.WorkoutViewModel
import com.rayliu.gymnote.wearos.workoutlist.WorkoutListScreen
import com.rayliu.gymnote.wearos.workoutlist.WorkoutListViewModel
import kotlinx.collections.immutable.persistentListOf
import kotlinx.datetime.toLocalTime
import org.koin.androidx.compose.navigation.koinNavViewModel

fun NavGraphBuilder.mainNavGraph(
Expand Down Expand Up @@ -153,18 +158,62 @@ fun NavGraphBuilder.mainNavGraph(
nullable = false
}
)
) {
) { entry ->
val focusRequester = remember { FocusRequester() }
val viewModel: AddRecordViewModel = koinNavViewModel()
viewModel.performPreScreenTasks()

val recordTypes = viewModel.recordInputTypes.value
val userInputTimeRecord =
entry.savedStateHandle.get<String>(TIME_PICKER_RESULT_NAV_ARGUMENT)
viewModel.setTimeRecord(userInputTimeRecord)
val timeRecord = viewModel.timeRecord.value ?: DEFAULT_TIME_RECORD

AddRecordScreen(
recordTypes = recordTypes,
focusRequester = focusRequester,
onRequestFocus = {
RequestFocusOnResume(it)
},
onCancelButtonClicked = {
navController.popBackStack()
},
onTimeAdjustButtonClicked = {
navController.navigate(
Screen.TimePickerScreen.route + "?$TIME_PICKER_NAV_ARGUMENT=$timeRecord"
)
},
userInputTimeRecord = timeRecord
)
}
composable(
route = Screen.TimePickerScreen.route +
"?$TIME_PICKER_NAV_ARGUMENT={$TIME_PICKER_NAV_ARGUMENT}",
arguments = listOf(
navArgument(SCROLL_TYPE_NAV_ARGUMENT) {
type = NavType.EnumType(DestinationScrollType::class.java)
defaultValue = DestinationScrollType.NONE
},
navArgument(TIME_PICKER_NAV_ARGUMENT) {
type = NavType.StringType
defaultValue = DEFAULT_TIME_RECORD
nullable = true
}
)
) { entry ->
val focusRequester = remember { FocusRequester() }
val defaultTime = entry.arguments?.getString(TIME_PICKER_NAV_ARGUMENT)
TimePickerScreen(
focusRequester = focusRequester,
onTimeConfirm = { resultTime ->
navController.previousBackStackEntry
?.savedStateHandle
?.set(TIME_PICKER_RESULT_NAV_ARGUMENT, resultTime)

navController.popBackStack()
},
defaultTime = defaultTime?.toLocalTime()
)
RequestFocusOnResume(focusRequester)
}
}
Expand Down
4 changes: 3 additions & 1 deletion wear/src/main/java/com/rayliu/gymnote/wearos/WearApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ fun WearApp(
}

key(backStackEntry.destination.route) {
TimeText(modifier = timeTextModifier ?: Modifier)
TimeText(
modifier = timeTextModifier ?: Modifier
)
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
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.FocusRequester
Expand All @@ -33,6 +36,9 @@ fun AddRecordScreen(
recordTypes: ImmutableSet<RecordType>,
focusRequester: FocusRequester,
onCancelButtonClicked: () -> Unit,
onTimeAdjustButtonClicked: () -> Unit,
onRequestFocus: @Composable (FocusRequester) -> Unit,
userInputTimeRecord: String?,
modifier: Modifier = Modifier
) {
Box(
Expand All @@ -52,7 +58,13 @@ fun AddRecordScreen(
) { page ->
for (recordType in recordTypes) {
if (page == recordTypes.indexOf(recordType)) {
ShowScreenByRecordType(focusRequester, recordType)
ShowScreenByRecordType(
focusRequester,
recordType,
onTimeAdjustButtonClicked,
userInputTimeRecord
)
onRequestFocus(focusRequester)
}
}

Expand Down Expand Up @@ -85,29 +97,54 @@ fun AddRecordScreen(
private fun ShowScreenByRecordType(
focusRequester: FocusRequester,
recordType: RecordType,
onTimeAdjustButtonClicked: () -> Unit,
userInputTimeRecord: String?
) {
when (recordType) {
RecordType.WEIGHT -> {
val defaultText = "0.0"
var userInput by remember { mutableStateOf(defaultText) }
AddWeightRecordScreen(
focusRequester = focusRequester,
valueUnit = "kg",
defaultText = defaultText,
userInput = userInput,
onInputChanged = { userInput = it },
modifier = Modifier
)
}

RecordType.REPS -> {
val defaultText = "0"
var userInput by remember { mutableStateOf(defaultText) }
AddRepsRecordScreen(
focusRequester = focusRequester,
valueUnit = "reps",
defaultText = defaultText,
userInput = userInput,
onInputChanged = { userInput = it },
modifier = Modifier
)
}

RecordType.TIME -> {
AddTimeRecordScreen(
modifier = Modifier
onAdjustButtonClicked = onTimeAdjustButtonClicked,
focusRequester = focusRequester,
modifier = Modifier,
defaultText = userInputTimeRecord
)
}

RecordType.DISTANCE -> {
val defaultText = "0.0"
var userInput by remember { mutableStateOf(defaultText) }
AddDistanceRecordScreen(
focusRequester = focusRequester,
valueUnit = "km",
defaultText = defaultText,
userInput = userInput,
onInputChanged = { userInput = it },
modifier = Modifier
)
}
Expand Down Expand Up @@ -138,7 +175,10 @@ private fun AddRecordScreenPreview() {
AddRecordScreen(
persistentSetOf(),
focusRequester = FocusRequester(),
onCancelButtonClicked = {}
onRequestFocus = {},
onCancelButtonClicked = {},
onTimeAdjustButtonClicked = {},
userInputTimeRecord = null
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.rayliu.commonmain.domain.model.SportRecordType
import com.rayliu.commonmain.domain.model.WorkoutInfo
import com.rayliu.commonmain.domain.usecase.GetWorkoutInfo
import com.rayliu.gymnote.wearos.navigation.WORKOUT_ID_NAV_ARGUMENT
import kotlinx.collections.immutable.ImmutableSet
Expand All @@ -21,15 +20,12 @@ class AddRecordViewModel(

private val workoutId: Int = savedStateHandle[WORKOUT_ID_NAV_ARGUMENT] ?: -1

val workoutInfo = mutableStateOf<WorkoutInfo?>(null)
val recordInputTypes = mutableStateOf<ImmutableSet<RecordType>>(persistentSetOf())
val timeRecord = mutableStateOf<String?>(null)

fun performPreScreenTasks() {
viewModelScope.launch {
val info = getWorkoutInfo(workoutId).also {
workoutInfo.value = it
} ?: return@launch

val info = getWorkoutInfo(workoutId) ?: return@launch
when (info.sportRecordType) {
SportRecordType.WEIGHT_REPS -> {
recordInputTypes.value = persistentSetOf(RecordType.WEIGHT, RecordType.REPS)
Expand All @@ -56,4 +52,8 @@ class AddRecordViewModel(
}
}
}

fun setTimeRecord(userInputTimeRecord: String?) {
timeRecord.value = userInputTimeRecord
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@ package com.rayliu.gymnote.wearos.addrecord.recordinput

import android.widget.Toast
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.fillMaxSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Undo
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.alpha
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.wear.compose.material.CompactButton
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Text
import com.rayliu.gymnote.R
import com.rayliu.gymnote.wearos.theme.GymNoteTheme
import com.rayliu.gymnote.wearos.theme.PreviewConstants
Expand All @@ -24,38 +29,86 @@ import com.rayliu.gymnote.wearos.utils.InputUtils
@Composable
fun AddDistanceRecordScreen(
focusRequester: FocusRequester,
valueUnit: String,
defaultText: String,
userInput: String,
onInputChanged: (String) -> Unit,
modifier: Modifier = Modifier
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
modifier = modifier.fillMaxSize()
) {
val step = 1
val defaultText = "0"
var userInput by remember { mutableStateOf(defaultText) }
val step = 0.5f
val minimumValue = 0.0f

val context = LocalContext.current
val waringText = stringResource(id = R.string.warning_input_type_is_not_number)

val undoButtonVisibility = if (userInput != defaultText) {
1f
} else {
0f
}

Column(
verticalArrangement = Arrangement.Center
) {
CompactButton(
onClick = { onInputChanged(defaultText) },
modifier = Modifier.alpha(undoButtonVisibility)
) {
Icon(
imageVector = Icons.Rounded.Undo,
contentDescription = "undo"
)
}
}

ValueInput(
currentInput = userInput,
focusRequester = focusRequester,
onUserInputText = { result, minimumValue ->
isMinusValueEnabled = userInput.toFloat() > minimumValue,
onUserInputText = { result ->
val newInput = result?.toString()?.trim() ?: defaultText
if (InputUtils.isNumeric(newInput) && newInput.toInt() >= minimumValue) {
userInput = newInput
if (InputUtils.isNumeric(newInput) && newInput.toFloat() >= minimumValue) {
onInputChanged(newInput)
} else {
Toast.makeText(context, waringText, Toast.LENGTH_SHORT).show()
}
},
onUserClickPlusButton = {
userInput = (it.toInt() + step).toString()
val newInput = (it.toFloat() + step).toString()
onInputChanged(newInput)
},
onUserClickMinorButton = {
userInput = (it.toInt() - step).toString()
val value = it.toFloat()
if (value > minimumValue) {
val newInput = (value - step).toString()
onInputChanged(newInput)
}
}
)

Column(
verticalArrangement = Arrangement.Center
) {
Box {
// For layout only
CompactButton(
modifier = Modifier.alpha(0f),
enabled = false,
onClick = {}
) {}

Text(
valueUnit,
textAlign = TextAlign.Center,
modifier = Modifier.align(Alignment.Center)
)
}
}
}
}

Expand All @@ -69,7 +122,11 @@ fun AddDistanceRecordScreen(
private fun AddDistanceRecordPreview() {
GymNoteTheme {
AddDistanceRecordScreen(
FocusRequester()
FocusRequester(),
valueUnit = "km",
defaultText = "0",
userInput = "0",
onInputChanged = {}
)
}
}
Loading

0 comments on commit feebf1a

Please sign in to comment.