Skip to content
This repository has been archived by the owner on Mar 18, 2024. It is now read-only.

Commit

Permalink
Support barbells in plate calculator and other fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
AnkitSuda committed Nov 28, 2022
1 parent 59a2b2a commit cf91c9d
Show file tree
Hide file tree
Showing 28 changed files with 473 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import androidx.navigation.NavHostController
import com.ankitsuda.common.compose.collectEvent
import com.ankitsuda.navigation.*
import com.ankitsuda.rebound.ui.calendar.CalendarScreen
import com.ankitsuda.rebound.ui.components.workouteditor.barbellselector.BarbellSelectorBottomSheet
import com.ankitsuda.rebound.ui.components.workouteditor.supersetselector.SupersetSelectorBottomSheet
import com.ankitsuda.rebound.ui.create_exercise.CreateExerciseScreen
import com.ankitsuda.rebound.ui.customizebarbells.CustomizeBarbellsScreen
Expand Down Expand Up @@ -127,6 +128,7 @@ internal fun AppNavigation(
addExercisesBottomSheet(navController)
addRestTimer(navController)
addSupersetSelector(navController)
addBarbellSelector(navController)
}
}

Expand Down Expand Up @@ -415,6 +417,12 @@ private fun NavGraphBuilder.addSupersetSelector(navController: NavController) {
}
}

private fun NavGraphBuilder.addBarbellSelector(navController: NavController) {
bottomSheetScreen(LeafScreen.BarbellSelector()) {
BarbellSelectorBottomSheet(navController)
}
}

/**
* Adds an [NavController.OnDestinationChangedListener] to this [NavController] and updates the
* returned [State] which is updated as the destination changes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.ankitsuda.rebound.domain.entities.Barbell


@Composable
Expand All @@ -32,6 +33,7 @@ fun ExercisePopupMenu(
onAddWarmUpSets: () -> Unit,
onAddNote: () -> Unit,
onAddToSuperset: () -> Unit,
onChangeBarbell: () -> Unit,
onRemoveFromSuperset: () -> Unit,
) {
DropdownMenu(
Expand Down Expand Up @@ -61,6 +63,12 @@ fun ExercisePopupMenu(
}) {
Text(stringResource(id = if (isInSuperset) R.string.remove_from_superset else R.string.add_to_superset))
}
DropdownMenuItem(onClick = {
onDismissRequest()
onChangeBarbell()
}) {
Text(stringResource(id = R.string.barbell))
}
DropdownMenuItem(onClick = {
onDismissRequest()
onDeleteExercise()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,9 @@ import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.ankitsuda.common.compose.SAFE_RS_KEYBOARD_HEIGHT
import com.ankitsuda.navigation.*
import com.ankitsuda.rebound.domain.entities.ExerciseLogEntry
import com.ankitsuda.rebound.domain.entities.ExerciseSetGroupNote
import com.ankitsuda.rebound.domain.entities.ExerciseWorkoutJunction
import com.ankitsuda.rebound.domain.entities.LogEntriesWithExerciseJunction
import com.ankitsuda.rebound.domain.entities.*
import com.ankitsuda.rebound.ui.components.AppTextField
import com.ankitsuda.rebound.ui.components.workouteditor.barbellselector.models.BarbellSelectorResult
import com.ankitsuda.rebound.ui.components.workouteditor.supersetselector.models.SupersetSelectorResult
import com.ankitsuda.rebound.ui.components.workouteditor.warmupcalculator.toExerciseLogEntries
import com.ankitsuda.rebound.ui.keyboard.LocalReboundSetKeyboard
Expand All @@ -58,6 +56,7 @@ fun WorkoutEditorComponent(
workoutNote: String?,
cancelWorkoutButtonVisible: Boolean,
logEntriesWithJunction: List<LogEntriesWithExerciseJunction>,
barbells: List<Barbell>,
onChangeWorkoutName: (String) -> Unit,
onChangeWorkoutNote: (String) -> Unit,
onAddExerciseToWorkout: (exerciseId: String) -> Unit,
Expand All @@ -72,6 +71,7 @@ fun WorkoutEditorComponent(
onChangeNote: (ExerciseSetGroupNote) -> Unit,
onAddToSuperset: (junctionId: String, supersetId: Int) -> Unit,
onRemoveFromSuperset: (LogEntriesWithExerciseJunction) -> Unit,
onUpdateBarbell: (junctionId: String, barbellId: String) -> Unit,
layoutAtTop: @Composable LazyItemScope.() -> Unit = {}
) {
// Observes results when ExercisesScreen changes value of arg
Expand All @@ -85,6 +85,12 @@ fun WorkoutEditorComponent(
?.getStateFlow<SupersetSelectorResult?>(RESULT_SUPERSET_SELECTOR_SUPERSET_ID_KEY, null)
?.collectAsState()

// Observes results when Barbell Selector changes value of arg
val barbellSelectorResult = navController.currentBackStackEntry
?.savedStateHandle
?.getStateFlow<BarbellSelectorResult?>(RESULT_BARBELL_SELECTOR_KEY, null)
?.collectAsState()

val navigationBarHeight =
with(LocalDensity.current) { if (addNavigationBarPadding) LocalWindowInsets.current.navigationBars.bottom.toDp() else 0.dp }

Expand Down Expand Up @@ -115,6 +121,17 @@ fun WorkoutEditorComponent(
}
}

LaunchedEffect(key1 = barbellSelectorResult?.value) {
barbellSelectorResult?.value?.let { result ->
onUpdateBarbell(result.junctionId, result.barbellId)

navController.currentBackStackEntry?.savedStateHandle?.set(
RESULT_BARBELL_SELECTOR_KEY,
null
)
}
}

val keyboardController = LocalSoftwareKeyboardController.current
val reboundKeyboard = LocalReboundSetKeyboard.current
fun hideKeyboard() {
Expand Down Expand Up @@ -182,6 +199,7 @@ fun WorkoutEditorComponent(
workoutExerciseItemAlt(
useReboundKeyboard = useReboundKeyboard,
logEntriesWithJunction = logEntriesWithJunctionItem,
barbells = barbells,
onValuesUpdated = { updatedEntry ->
onUpdateLogEntry(updatedEntry)
},
Expand Down Expand Up @@ -223,6 +241,14 @@ fun WorkoutEditorComponent(
junctionId = logEntriesWithJunctionItem.junction.id,
)
)
},
onRequestBarbellChanger = {
navigator.navigate(
LeafScreen.BarbellSelector.createRoute(
junctionId = logEntriesWithJunctionItem.junction.id,
selectedBarbellId = logEntriesWithJunctionItem.junction.barbellId
)
)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ import com.ankitsuda.rebound.domain.DistanceUnit
import com.ankitsuda.rebound.domain.ExerciseCategory
import com.ankitsuda.rebound.domain.LogSetType
import com.ankitsuda.rebound.domain.WeightUnit
import com.ankitsuda.rebound.domain.entities.Exercise
import com.ankitsuda.rebound.domain.entities.ExerciseLogEntry
import com.ankitsuda.rebound.domain.entities.ExerciseSetGroupNote
import com.ankitsuda.rebound.domain.entities.LogEntriesWithExerciseJunction
import com.ankitsuda.rebound.domain.entities.*
import com.ankitsuda.rebound.ui.components.RButton
import com.ankitsuda.rebound.ui.components.RSpacer
import com.ankitsuda.rebound.ui.components.workouteditor.warmupcalculator.WarmUpCalculatorDialog
Expand All @@ -64,6 +61,7 @@ private val ExerciseLogEntryComparator = Comparator<ExerciseLogEntry> { left, ri
fun LazyListScope.workoutExerciseItemAlt(
useReboundKeyboard: Boolean = false,
logEntriesWithJunction: LogEntriesWithExerciseJunction,
barbells: List<Barbell>,
onUpdateWarmUpSets: (List<WarmUpSet>) -> Unit,
onValuesUpdated: (updatedEntry: ExerciseLogEntry) -> Unit,
onSwipeDelete: (ExerciseLogEntry) -> Unit,
Expand All @@ -74,13 +72,16 @@ fun LazyListScope.workoutExerciseItemAlt(
onChangeNote: (ExerciseSetGroupNote) -> Unit,
onAddToSuperset: () -> Unit,
onRemoveFromSuperset: () -> Unit,
onRequestBarbellChanger: () -> Unit,
) {

val supersetId = logEntriesWithJunction.junction.supersetId
val exercise = logEntriesWithJunction.exercise
val logEntries = logEntriesWithJunction.logEntries
val notes = logEntriesWithJunction.notes ?: emptyList()
val sortedEntries = logEntries.sortedWith(ExerciseLogEntryComparator)
val barbell = barbells.find { b -> b.id == logEntriesWithJunction.junction.barbellId }


// Exercise info
item(key = "${logEntriesWithJunction.junction.id}_exercise_info") {
Expand Down Expand Up @@ -177,7 +178,8 @@ fun LazyListScope.workoutExerciseItemAlt(
},
onAddNote = onAddEmptyNote,
onAddToSuperset = onAddToSuperset,
onRemoveFromSuperset = onRemoveFromSuperset
onRemoveFromSuperset = onRemoveFromSuperset,
onChangeBarbell = onRequestBarbellChanger,
)
}

Expand Down Expand Up @@ -302,12 +304,14 @@ fun LazyListScope.workoutExerciseItemAlt(
it.entryId
}) { entry ->
val appSettings = LocalAppSettings.current
key(appSettings.weightUnit, appSettings.distanceUnit) {

key(barbell, appSettings.weightUnit, appSettings.distanceUnit) {
SetItem(
useReboundKeyboard = useReboundKeyboard,
revisedSetText = revisedSetsTexts[sortedEntries.indexOf(entry)],
exercise = exercise,
exerciseLogEntry = entry,
barbell = barbell,
onChange = {
onValuesUpdated(it)
},
Expand Down Expand Up @@ -349,6 +353,7 @@ fun LazyListScope.workoutExerciseItemAlt(
private fun LazyItemScope.SetItem(
exercise: Exercise,
useReboundKeyboard: Boolean,
barbell: Barbell?,
revisedSetText: Pair<String, Color?>,
exerciseLogEntry: ExerciseLogEntry,
onChange: (ExerciseLogEntry) -> Unit,
Expand All @@ -358,14 +363,6 @@ private fun LazyItemScope.SetItem(
mutableStateOf(exerciseLogEntry)
}

// LaunchedEffect(key1 = exerciseLogEntry) {
// // We have to change saved rpe manually because
// // main rpe change is not handled by SetItem function
// if (exerciseLogEntry.rpe != mLogEntry.rpe) {
// mLogEntry = mLogEntry.copy(rpe = exerciseLogEntry.rpe)
// }
// }

val completionAnimDuration = 200
val completionAnimSpecFloat =
tween<Float>(
Expand Down Expand Up @@ -461,6 +458,7 @@ private fun LazyItemScope.SetItem(
exercise = exercise,
exerciseLogEntry = mLogEntry,
revisedSetText = revisedSetText,
barbell = barbell,
onWeightChange = { _, value ->
handleOnChange(mLogEntry.copy(weight = value))
},
Expand Down Expand Up @@ -494,6 +492,7 @@ private fun SetItemLayout(
exercise: Exercise,
exerciseLogEntry: ExerciseLogEntry,
revisedSetText: Pair<String, Color?>,
barbell: Barbell?,
onWeightChange: (ExerciseLogEntry, Double?) -> Unit,
onRepsChange: (ExerciseLogEntry, Int?) -> Unit,
onDistanceChange: (ExerciseLogEntry, Double?) -> Unit,
Expand Down Expand Up @@ -598,7 +597,8 @@ private fun SetItemLayout(
bgColor = bgColor,
reboundKeyboardType = getReboundKeyboardType(
category = exercise.category,
isLeft = true
isLeft = true,
barbell = barbell,
),
)
} else {
Expand Down Expand Up @@ -663,7 +663,7 @@ private fun SetItemLayout(
},
contentColor = contentColor,
bgColor = bgColor,
reboundKeyboardType = ReboundKeyboardType.RPE
reboundKeyboardType = ReboundKeyboardType.Rpe
)
}

Expand Down Expand Up @@ -696,11 +696,17 @@ private fun SetItemLayout(
}
}

private fun getReboundKeyboardType(category: ExerciseCategory, isLeft: Boolean) =
private fun getReboundKeyboardType(
category: ExerciseCategory,
isLeft: Boolean,
barbell: Barbell? = null
) =
when (category) {
ExerciseCategory.WEIGHTS_AND_REPS -> if (isLeft) ReboundKeyboardType.WEIGHT else ReboundKeyboardType.REPS
ExerciseCategory.REPS -> ReboundKeyboardType.REPS
ExerciseCategory.DISTANCE_AND_TIME -> if (isLeft) ReboundKeyboardType.DISTANCE else ReboundKeyboardType.TIME
ExerciseCategory.TIME -> ReboundKeyboardType.TIME
ExerciseCategory.UNKNOWN -> ReboundKeyboardType.REPS
ExerciseCategory.WEIGHTS_AND_REPS -> if (isLeft) ReboundKeyboardType.Weight(
barbell = barbell
) else ReboundKeyboardType.Reps
ExerciseCategory.REPS -> ReboundKeyboardType.Reps
ExerciseCategory.DISTANCE_AND_TIME -> if (isLeft) ReboundKeyboardType.Distance else ReboundKeyboardType.Time
ExerciseCategory.TIME -> ReboundKeyboardType.Time
ExerciseCategory.UNKNOWN -> ReboundKeyboardType.Reps
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2022 Ankit Suda.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This software 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 General Public License for more details.
*/

package com.ankitsuda.rebound.ui.components.workouteditor.barbellselector

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.ankitsuda.navigation.LocalNavigator
import com.ankitsuda.navigation.Navigator
import com.ankitsuda.navigation.RESULT_BARBELL_SELECTOR_KEY
import com.ankitsuda.navigation.RESULT_SUPERSET_SELECTOR_SUPERSET_ID_KEY
import com.ankitsuda.rebound.domain.entities.Barbell
import com.ankitsuda.rebound.domain.entities.ExerciseWorkoutJunction
import com.ankitsuda.rebound.ui.components.BottomSheetSurface
import com.ankitsuda.rebound.ui.components.TopBar
import com.ankitsuda.rebound.ui.components.workouteditor.R
import com.ankitsuda.rebound.ui.components.workouteditor.barbellselector.components.BarbellSelectorListItem
import com.ankitsuda.rebound.ui.components.workouteditor.barbellselector.models.BarbellSelectorResult
import com.ankitsuda.rebound.ui.components.workouteditor.supersetselector.components.SupersetExerciseListItem
import com.ankitsuda.rebound.ui.components.workouteditor.supersetselector.models.SupersetSelectorResult

@Composable
fun BarbellSelectorBottomSheet(
navController: NavController,
navigator: Navigator = LocalNavigator.current,
viewModel: BarbellSelectorBottomSheetViewModel = hiltViewModel()
) {
val junctionId = viewModel.junctionId
val initialSelectedBarbellId = viewModel.selectedBarbellId
val barbells by viewModel.barbells.collectAsState(initial = emptyList())

fun handleItemClick(barbell: Barbell) {
navController.previousBackStackEntry?.savedStateHandle?.set(
RESULT_BARBELL_SELECTOR_KEY,
BarbellSelectorResult(
junctionId = junctionId,
barbellId = barbell.id,
)
)
navController.popBackStack()
}

BottomSheetSurface {
LazyColumn(
Modifier
.fillMaxWidth(),
contentPadding =
WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
.asPaddingValues()
) {
item {
TopBar(
title = stringResource(id = R.string.select_barbell),
statusBarEnabled = false,
elevationEnabled = false
)
}

itemsIndexed(barbells, key = { _, barbell ->
barbell.id
}) { index, barbell ->
BarbellSelectorListItem(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = if (index == barbells.size - 1) 8.dp else 0.dp),
barbell = barbell,
isSelected = barbell.id == initialSelectedBarbellId,
onClick = {
handleItemClick(barbell)
}
)
}
}
}
}
Loading

0 comments on commit cf91c9d

Please sign in to comment.