diff --git a/app/build.gradle b/app/build.gradle index bf740c82..7f0c4574 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,6 +111,7 @@ dependencies { implementation project(":modules:ui-customize-plates") implementation project(":modules:common-ui-components-workout-editor") implementation project(":modules:stopwatch") + implementation project(":modules:ui-customize-barbells") implementation Deps.Kotlin.coroutinesAndroid kapt Deps.Android.Lifecycle.compiler diff --git a/app/src/main/java/com/ankitsuda/rebound/ui/navigation/AppNavigation.kt b/app/src/main/java/com/ankitsuda/rebound/ui/navigation/AppNavigation.kt index e2ddaf22..b6e3ec2a 100644 --- a/app/src/main/java/com/ankitsuda/rebound/ui/navigation/AppNavigation.kt +++ b/app/src/main/java/com/ankitsuda/rebound/ui/navigation/AppNavigation.kt @@ -27,6 +27,8 @@ import com.ankitsuda.navigation.* import com.ankitsuda.rebound.ui.calendar.CalendarScreen import com.ankitsuda.rebound.ui.components.workouteditor.supersetselector.SupersetSelectorBottomSheet import com.ankitsuda.rebound.ui.create_exercise.CreateExerciseScreen +import com.ankitsuda.rebound.ui.customizebarbells.CustomizeBarbellsScreen +import com.ankitsuda.rebound.ui.customizebarbells.edit.BarbellEditBottomSheet import com.ankitsuda.rebound.ui.customizeplates.CustomizePlatesScreen import com.ankitsuda.rebound.ui.customizeplates.edit.PlateEditBottomSheet import com.ankitsuda.rebound.ui.exercise_details.ExerciseDetailScreen @@ -61,9 +63,7 @@ import com.google.accompanist.navigation.material.ExperimentalMaterialNavigation import kotlinx.coroutines.InternalCoroutinesApi @OptIn( - InternalCoroutinesApi::class, - ExperimentalMaterialNavigationApi::class, - androidx.compose.animation.ExperimentalAnimationApi::class + ExperimentalAnimationApi::class ) @Composable internal fun AppNavigation( @@ -190,6 +190,7 @@ private fun NavGraphBuilder.addMoreRoot(navController: NavController) { addPartMeasurementsScreen(navController) addSettingsScreen(navController) addCustomizePlatesScreen(navController) + addCustomizeBarbellsScreen(navController) addPersonalizationScreen(navController) addMainColorsPersonalizationScreen(navController) addShapesPersonalizationScreen(navController) @@ -204,6 +205,7 @@ private fun NavGraphBuilder.addMoreRoot(navController: NavController) { addAddPartMeasurementBottomSheet(navController) addPlateEditBottomSheet(navController) + addBarbellEditBottomSheet(navController) } } @@ -293,6 +295,12 @@ private fun NavGraphBuilder.addCustomizePlatesScreen(navController: NavControlle } } +private fun NavGraphBuilder.addCustomizeBarbellsScreen(navController: NavController) { + composableScreen(LeafScreen.Barbells()) { + CustomizeBarbellsScreen() + } +} + private fun NavGraphBuilder.addPersonalizationScreen(navController: NavController) { composableScreen(LeafScreen.Personalization()) { PersonalizationScreen(navController) @@ -383,6 +391,12 @@ private fun NavGraphBuilder.addPlateEditBottomSheet(navController: NavController } } +private fun NavGraphBuilder.addBarbellEditBottomSheet(navController: NavController) { + bottomSheetScreen(LeafScreen.BarbellEdit()) { + BarbellEditBottomSheet() + } +} + private fun NavGraphBuilder.addTemplatesFolderEditBottomSheet(navController: NavController) { bottomSheetScreen(LeafScreen.TemplatesFolderEdit()) { TemplatesFolderEditBottomSheet() diff --git a/modules/base-android/src/main/java/com/ankitsuda/base/util/Utils.kt b/modules/base-android/src/main/java/com/ankitsuda/base/util/Utils.kt index 19a72d7e..c7ffff18 100644 --- a/modules/base-android/src/main/java/com/ankitsuda/base/util/Utils.kt +++ b/modules/base-android/src/main/java/com/ankitsuda/base/util/Utils.kt @@ -38,6 +38,7 @@ fun Double.fromKmToMiles() = this * MILES_IN_KM fun Double.fromKgToLbsReadable() = DecimalFormat("#.##").format(fromKgToLbs()) fun Double.kgToReadable() = DecimalFormat("#.##").format(this) +fun Double.lbsToReadable() = kgToReadable() fun Double.fromKmToMilesReadable(): String = DecimalFormat("#.###").format(fromKmToMiles()) fun Double.kmToReadable(): String = DecimalFormat("#.###").format(this) \ No newline at end of file diff --git a/modules/common-ui-compose/src/main/java/com/ankitsuda/common/compose/Utils.kt b/modules/common-ui-compose/src/main/java/com/ankitsuda/common/compose/Utils.kt index 45207ad2..e049f6fd 100644 --- a/modules/common-ui-compose/src/main/java/com/ankitsuda/common/compose/Utils.kt +++ b/modules/common-ui-compose/src/main/java/com/ankitsuda/common/compose/Utils.kt @@ -34,7 +34,7 @@ fun Double?.kgToUserPrefStr( " " } else { "" - } + userPrefWeightUnitStr() + } + userPrefWeightUnitStr(weightUnit = weightUnit) } else { "" } @@ -64,7 +64,10 @@ fun WeightUnit.localizedStr(case: Int = 2): String = when (this) { * @param case 0=Pascal Case, 1=Upper Case, 2=Lower Case */ @Composable -fun userPrefWeightUnitStr(case: Int = 2): String = LocalAppSettings.current.weightUnit.localizedStr(case = case) +fun userPrefWeightUnitStr( + case: Int = 2, + weightUnit: WeightUnit = LocalAppSettings.current.weightUnit +): String = weightUnit.localizedStr(case = case) @Composable fun Double?.kmToUserPrefStr( diff --git a/modules/common-ui-icons/src/main/java/com/ankitsuda/rebound/ui/icons/Barbell.kt b/modules/common-ui-icons/src/main/java/com/ankitsuda/rebound/ui/icons/Barbell.kt new file mode 100644 index 00000000..2cdba60e --- /dev/null +++ b/modules/common-ui-icons/src/main/java/com/ankitsuda/rebound/ui/icons/Barbell.kt @@ -0,0 +1,56 @@ +package com.ankitsuda.rebound.ui.icons + +import androidx.compose.material.icons.Icons +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType +import androidx.compose.ui.graphics.PathFillType.Companion.NonZero +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.graphics.StrokeCap.Companion.Butt +import androidx.compose.ui.graphics.StrokeJoin +import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.unit.dp + +public val Icons.Filled.Barbell: ImageVector + get() { + if (_barbell != null) { + return _barbell!! + } + _barbell = Builder(name = "Barbell", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp, + viewportWidth = 24.0f, viewportHeight = 24.0f).apply { + path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f, + strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, + pathFillType = NonZero) { + moveTo(4.052f, 2.6378f) + lineToRelative(17.3101f, 17.3101f) + lineToRelative(-1.4142f, 1.4142f) + lineToRelative(-17.3101f, -17.3101f) + close() + } + path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f, + strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, + pathFillType = NonZero) { + moveTo(8.0628f, 3.8201f) + lineToRelative(1.731f, 1.731f) + lineToRelative(-4.2426f, 4.2426f) + lineToRelative(-1.731f, -1.731f) + close() + } + path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f, + strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, + pathFillType = NonZero) { + moveTo(18.4488f, 14.2062f) + lineToRelative(1.731f, 1.731f) + lineToRelative(-4.2426f, 4.2426f) + lineToRelative(-1.731f, -1.731f) + close() + } + } + .build() + return _barbell!! + } + +private var _barbell: ImageVector? = null diff --git a/modules/common-ui-resources/src/main/res/values/strings.xml b/modules/common-ui-resources/src/main/res/values/strings.xml index e15fd1ce..a38f2da0 100644 --- a/modules/common-ui-resources/src/main/res/values/strings.xml +++ b/modules/common-ui-resources/src/main/res/values/strings.xml @@ -146,6 +146,7 @@ Perform Again Edit session Customize barbell plates + Customize barbells Defaults Weight Unit Metric (kg) @@ -212,6 +213,8 @@ Set Keyboard Demo Plate Weight + Weight (kg) + Weight (lbs) Color Height multiplier Width multiplier @@ -252,4 +255,7 @@ Start time End time Start time is longer than end time + Barbells + Barbell + Add barbell \ No newline at end of file diff --git a/modules/core-data/schemas/com.ankitsuda.rebound.data.db.AppDatabase/1.json b/modules/core-data/schemas/com.ankitsuda.rebound.data.db.AppDatabase/1.json index e024930c..f2a35d12 100644 --- a/modules/core-data/schemas/com.ankitsuda.rebound.data.db.AppDatabase/1.json +++ b/modules/core-data/schemas/com.ankitsuda.rebound.data.db.AppDatabase/1.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "78f1033c7025b8448214463c96e35563", + "identityHash": "68617553ff75764b3f0264b855b8cd96", "entities": [ { "tableName": "body_parts", @@ -841,12 +841,68 @@ }, "indices": [], "foreignKeys": [] + }, + { + "tableName": "barbells", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT, `weight_kg` REAL, `weight_lbs` REAL, `is_active` INTEGER, `created_at` INTEGER, `update_at` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "weightKg", + "columnName": "weight_kg", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "weightLbs", + "columnName": "weight_lbs", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "isActive", + "columnName": "is_active", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "updatedAt", + "columnName": "update_at", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] } ], "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '78f1033c7025b8448214463c96e35563')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '68617553ff75764b3f0264b855b8cd96')" ] } } \ No newline at end of file diff --git a/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/AppDatabase.kt b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/AppDatabase.kt index 63a0a672..fc2a139b 100644 --- a/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/AppDatabase.kt +++ b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/AppDatabase.kt @@ -39,6 +39,7 @@ import kotlinx.coroutines.launch ThemePreset::class, ExerciseSetGroupNote::class, WorkoutTemplatesFolder::class, + Barbell::class ], version = 1, exportSchema = true @@ -54,6 +55,7 @@ abstract class AppDatabase : RoomDatabase() { abstract fun platesDao(): PlatesDao abstract fun themePresetsDao(): ThemePresetsDao abstract fun workoutFoldersFoldersDao(): WorkoutFoldersFoldersDao + abstract fun barbellsDao(): BarbellsDao companion object { @Volatile diff --git a/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/DatabaseModule.kt b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/DatabaseModule.kt index d6acc895..f8a2f991 100644 --- a/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/DatabaseModule.kt +++ b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/DatabaseModule.kt @@ -62,4 +62,7 @@ class DatabaseModule { @Provides fun provideWorkoutFoldersFoldersDao(db: AppDatabase) = db.workoutFoldersFoldersDao() + @Provides + fun provideBarbellsDao(db: AppDatabase) = db.barbellsDao() + } diff --git a/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/daos/BarbellsDao.kt b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/daos/BarbellsDao.kt new file mode 100644 index 00000000..0731b09d --- /dev/null +++ b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/db/daos/BarbellsDao.kt @@ -0,0 +1,50 @@ +/* + * 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.data.db.daos + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.ankitsuda.rebound.domain.WeightUnit +import com.ankitsuda.rebound.domain.entities.Muscle +import com.ankitsuda.rebound.domain.entities.Barbell +import kotlinx.coroutines.flow.Flow + +@Dao +interface BarbellsDao { + + @Query("SELECT * FROM barbells WHERE id = :id") + fun getBarbell(id: String): Flow + + @Query("SELECT * FROM barbells ORDER BY name") + fun getBarbells(): Flow> + + @Query("SELECT * FROM barbells WHERE is_active = 1 ORDER BY name") + fun getActiveBarbells(): Flow> + + @Query("UPDATE barbells SET is_active = :isActive WHERE id = :barbellId") + suspend fun updateIsActive(barbellId: String, isActive: Boolean) + + @Insert + suspend fun insertBarbells(barbells: List) + + @Query("DELETE FROM barbells WHERE id = :barbellId") + suspend fun deleteBarbell(barbellId: String) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertBarbell(barbell: Barbell) + +} \ No newline at end of file diff --git a/modules/core-data/src/main/java/com/ankitsuda/rebound/data/repositories/BarbellsRepository.kt b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/repositories/BarbellsRepository.kt new file mode 100644 index 00000000..034eb375 --- /dev/null +++ b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/repositories/BarbellsRepository.kt @@ -0,0 +1,40 @@ +/* + * 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.data.repositories + +import com.ankitsuda.rebound.data.db.daos.BarbellsDao +import com.ankitsuda.rebound.domain.WeightUnit +import com.ankitsuda.rebound.domain.entities.Barbell +import javax.inject.Inject + +class BarbellsRepository @Inject constructor(private val barbellsDao: BarbellsDao) { + + fun getBarbells() = barbellsDao.getBarbells() + + fun getActiveBarbells() = barbellsDao.getActiveBarbells() + + fun getBarbell(barbellId: String) = barbellsDao.getBarbell(barbellId) + + suspend fun upsertBarbell(barbell: Barbell) = barbellsDao.insertBarbell(barbell) + + suspend fun updateIsActive(barbellId: String, isActive: Boolean) { + barbellsDao.updateIsActive(barbellId, isActive) + } + + suspend fun deleteBarbell(barbellId: String) { + barbellsDao.deleteBarbell(barbellId) + } + +} \ No newline at end of file diff --git a/modules/core-data/src/main/java/com/ankitsuda/rebound/data/repositories/RepositoriesModule.kt b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/repositories/RepositoriesModule.kt index 8b812f6d..4c82f833 100644 --- a/modules/core-data/src/main/java/com/ankitsuda/rebound/data/repositories/RepositoriesModule.kt +++ b/modules/core-data/src/main/java/com/ankitsuda/rebound/data/repositories/RepositoriesModule.kt @@ -68,4 +68,11 @@ class RepositoriesModule { presetsDao: ThemePresetsDao ) = ThemePresetsRepository(presetsDao) + + @Singleton + @Provides + fun provideBarbellsRepository( + barbellsDao: BarbellsDao + ) = + BarbellsRepository(barbellsDao) } \ No newline at end of file diff --git a/modules/domain/src/main/java/com/ankitsuda/rebound/domain/entities/Barbell.kt b/modules/domain/src/main/java/com/ankitsuda/rebound/domain/entities/Barbell.kt new file mode 100644 index 00000000..93129d4b --- /dev/null +++ b/modules/domain/src/main/java/com/ankitsuda/rebound/domain/entities/Barbell.kt @@ -0,0 +1,47 @@ +/* + * 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.domain.entities + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.ankitsuda.rebound.domain.ExerciseCategory +import com.ankitsuda.rebound.domain.WeightUnit +import java.time.LocalDateTime +import java.util.* + +@Entity(tableName = "barbells") +data class Barbell( + @PrimaryKey(autoGenerate = false) + @ColumnInfo(name = "id") + val id: String, + + @ColumnInfo(name = "name") + var name: String? = null, + + @ColumnInfo(name = "weight_kg") + var weightKg: Double? = null, + + @ColumnInfo(name = "weight_lbs") + var weightLbs: Double? = null, + + @ColumnInfo(name = "is_active") + var isActive: Boolean? = null, + + @ColumnInfo(name = "created_at") + var createdAt: LocalDateTime? = null, + @ColumnInfo(name = "update_at") + var updatedAt: LocalDateTime? = null, +) \ No newline at end of file diff --git a/modules/navigation/src/main/java/com/ankitsuda/navigation/Screens.kt b/modules/navigation/src/main/java/com/ankitsuda/navigation/Screens.kt index c46bb3f0..2088f6ac 100644 --- a/modules/navigation/src/main/java/com/ankitsuda/navigation/Screens.kt +++ b/modules/navigation/src/main/java/com/ankitsuda/navigation/Screens.kt @@ -45,6 +45,7 @@ const val FOLDER_ID_KEY = "folder_id" const val SUPERSET_ID_KEY = "superset_id" const val JUNCTION_ID_KEY = "junction_id" const val ENTRY_ID_KEY = "entry_id" +const val BARBELL_ID_KEY = "barbell_id" const val RESULT_EXERCISES_SCREEN_EXERCISE_ID = "result_exercises_screen_exercise_id" const val RESULT_SUPERSET_SELECTOR_SUPERSET_ID_KEY = "result_superset_selector_superset_id" @@ -225,6 +226,38 @@ sealed class LeafScreen( } } + data class Barbells( + override val route: String = "barbells", + override val root: TabRootScreen = TabRootScreen.MoreTab + ) : LeafScreen(route, root) + + data class BarbellEdit( + override val route: String = "barbells/edit?$BARBELL_ID_KEY={$BARBELL_ID_KEY}", + override val root: TabRootScreen = TabRootScreen.MoreTab + ) : LeafScreen( + route = route, + root = root, + arguments = listOf( + navArgument(BARBELL_ID_KEY) { + type = NavType.StringType + nullable = true + }, + ), + ) { + companion object { + fun createRoute( + plateId: String? = null, + root: TabRootScreen = TabRootScreen.MoreTab + ): String { + var str = "${root.route}/barbells/edit" + plateId?.let { + str += "?${BARBELL_ID_KEY}=$it" + } + return str; + } + } + } + data class Personalization( override val route: String = "personalization", override val root: TabRootScreen = TabRootScreen.MoreTab diff --git a/modules/ui-customize-barbells/build.gradle b/modules/ui-customize-barbells/build.gradle new file mode 100644 index 00000000..83e0b3ae --- /dev/null +++ b/modules/ui-customize-barbells/build.gradle @@ -0,0 +1,64 @@ +/* + * 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. + */ + +import com.ankitsuda.rebound.buildSrc.App +import com.ankitsuda.rebound.buildSrc.Deps + +plugins { + id "com.android.library" + id "dagger.hilt.android.plugin" + id "kotlin-android" + id "kotlin-kapt" + id "kotlin-parcelize" +} + +android { + compileSdkVersion App.compileSdkVersion + + defaultConfig { + minSdkVersion App.minSdkVersion + } + + compileOptions { + coreLibraryDesugaringEnabled true + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion Deps.Android.Compose.compilerVersion + } + namespace 'com.ankitsuda.rebound.ui.customizebarbells' +} + +repositories { + mavenCentral() +} + +dependencies { + api project(":modules:common-ui-compose") + api project(":modules:common-ui-theme") + api project(":modules:common-ui-components") + api project(":modules:core-data") + api project(":modules:navigation") + + implementation Deps.Dagger.hilt + kapt Deps.Dagger.hiltCompiler + + coreLibraryDesugaring Deps.Android.desugaring +} diff --git a/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/CustomizeBarbellsScreen.kt b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/CustomizeBarbellsScreen.kt new file mode 100644 index 00000000..58a7650b --- /dev/null +++ b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/CustomizeBarbellsScreen.kt @@ -0,0 +1,125 @@ +/* + * 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.customizebarbells + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Add +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.hilt.navigation.compose.hiltViewModel +import com.ankitsuda.navigation.LeafScreen +import com.ankitsuda.navigation.LocalNavigator +import com.ankitsuda.navigation.Navigator +import com.ankitsuda.rebound.domain.entities.Barbell +import com.ankitsuda.rebound.ui.components.TopBar2 +import com.ankitsuda.rebound.ui.components.TopBarBackIconButton +import com.ankitsuda.rebound.ui.components.TopBarIconButton +import com.ankitsuda.rebound.ui.customizebarbells.components.BarbellListItemComponent +import com.ankitsuda.rebound.ui.theme.ReboundTheme +import me.onebone.toolbar.CollapsingToolbarScaffold +import me.onebone.toolbar.ScrollStrategy +import me.onebone.toolbar.rememberCollapsingToolbarScaffoldState + +@Composable +fun CustomizeBarbellsScreen( + navigator: Navigator = LocalNavigator.current, + viewModel: CustomizeBarbellsScreenViewModel = hiltViewModel() +) { + val barbells by viewModel.barbells.collectAsState(initial = null) + + CustomizeBarbellsScreenLayout( + navigator = navigator, + barbells = barbells, + onUpdateIsActive = { id, isActive -> + viewModel.updateIsActive(id, isActive) + }, + onDeleteBarbell = { id -> + viewModel.deleteBarbell(id) + } + ) + +} + +@OptIn(ExperimentalFoundationApi::class) +@Composable +private fun CustomizeBarbellsScreenLayout( + navigator: Navigator, + barbells: List?, + onUpdateIsActive: (id: String, isActive: Boolean) -> Unit, + onDeleteBarbell: (id: String) -> Unit, +) { + val collapsingState = rememberCollapsingToolbarScaffoldState() + + CollapsingToolbarScaffold( + modifier = Modifier.background(ReboundTheme.colors.background), + scrollStrategy = ScrollStrategy.EnterAlwaysCollapsed, + state = collapsingState, + toolbar = { + TopBar2( + title = stringResource(id = R.string.barbells), + toolbarState = collapsingState.toolbarState, + navigationIcon = { + TopBarBackIconButton { + navigator.goBack() + } + }, + actions = { + TopBarIconButton( + icon = Icons.Outlined.Add, + title = stringResource(id = R.string.add_barbell), + onClick = { + navigator.navigate(LeafScreen.BarbellEdit.createRoute()) + } + ) + } + ) + }) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .background(ReboundTheme.colors.background), + ) { + if (barbells != null) { + items(items = barbells, key = { it.id }) { + BarbellListItemComponent( + modifier = Modifier + .fillMaxWidth() + .animateItemPlacement(), + barbell = it, + onUpdateIsActive = { newIsActive -> + onUpdateIsActive(it.id, newIsActive) + }, + onEditBarbell = { + navigator.navigate(LeafScreen.BarbellEdit.createRoute(it.id)) + }, + onDeleteBarbell = { + onDeleteBarbell(it.id) + } + ) + } + } + } + } +} \ No newline at end of file diff --git a/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/CustomizeBarbellsScreenViewModel.kt b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/CustomizeBarbellsScreenViewModel.kt new file mode 100644 index 00000000..56fdc83c --- /dev/null +++ b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/CustomizeBarbellsScreenViewModel.kt @@ -0,0 +1,44 @@ +/* + * 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.customizebarbells + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.ankitsuda.base.utils.extensions.shareWhileObserved +import com.ankitsuda.rebound.data.repositories.BarbellsRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class CustomizeBarbellsScreenViewModel @Inject constructor( + private val barbellsRepository: BarbellsRepository +) : ViewModel() { + val barbells = barbellsRepository.getBarbells() + .shareWhileObserved(viewModelScope) + + fun updateIsActive(barbellId: String, isActive: Boolean) { + viewModelScope.launch { + barbellsRepository.updateIsActive(barbellId, isActive) + } + } + + fun deleteBarbell(barbellId: String) { + viewModelScope.launch { + barbellsRepository.deleteBarbell(barbellId) + } + } +} \ No newline at end of file diff --git a/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/components/BarbellListItemComponent.kt b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/components/BarbellListItemComponent.kt new file mode 100644 index 00000000..9a16bd69 --- /dev/null +++ b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/components/BarbellListItemComponent.kt @@ -0,0 +1,119 @@ +/* + * 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.customizebarbells.components + +import androidx.compose.foundation.layout.* +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.Switch +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.MoreVert +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.ankitsuda.base.util.kgToReadable +import com.ankitsuda.base.util.lbsToReadable +import com.ankitsuda.base.util.toReadableString +import com.ankitsuda.common.compose.kgToUserPrefStr +import com.ankitsuda.common.compose.localizedStr +import com.ankitsuda.rebound.domain.WeightUnit +import com.ankitsuda.rebound.domain.entities.Barbell +import com.ankitsuda.rebound.ui.components.RSpacer +import com.ankitsuda.rebound.ui.customizebarbells.R +import com.ankitsuda.rebound.ui.theme.ReboundTheme + +@Composable +internal fun BarbellListItemComponent( + modifier: Modifier = Modifier, + barbell: Barbell, + onUpdateIsActive: (Boolean) -> Unit, + onDeleteBarbell: () -> Unit, + onEditBarbell: () -> Unit +) { + var isActive by remember(barbell.isActive) { + mutableStateOf(barbell.isActive ?: false) + } + + var menuExpanded by remember { + mutableStateOf(false) + } + + fun updateIsActive(active: Boolean) { + isActive = active + onUpdateIsActive(active) + } + + Box( + modifier = modifier + ) { + Row( + modifier = Modifier + .padding(start = 24.dp, end = 8.dp, bottom = 12.dp, top = 12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = barbell.name ?: "", + style = ReboundTheme.typography.body1, + color = ReboundTheme.colors.onBackground + ) + Text( + text = "${ + barbell.weightKg?.kgToReadable() + } ${WeightUnit.KG.localizedStr()} / ${ + barbell.weightLbs?.lbsToReadable() + } ${WeightUnit.LBS.localizedStr()}", + style = ReboundTheme.typography.body2, + color = ReboundTheme.colors.onBackground.copy(alpha = 0.75f) + ) + } + Switch( + checked = isActive, + onCheckedChange = { + updateIsActive(it) + } + ) + RSpacer(space = 4.dp) + IconButton(onClick = { + menuExpanded = true + }) { + Icon( + imageVector = Icons.Outlined.MoreVert, + contentDescription = stringResource(R.string.more), + tint = ReboundTheme.colors.onBackground + ) + + if (menuExpanded) { + BarbellMenuComponent( + expanded = menuExpanded, + onDismissRequest = { + menuExpanded = false + }, + onEditBarbell = onEditBarbell, + onDeleteBarbell = onDeleteBarbell + ) + } + + } + } + + } +} \ No newline at end of file diff --git a/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/components/BarbellMenuComponent.kt b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/components/BarbellMenuComponent.kt new file mode 100644 index 00000000..3830d9e8 --- /dev/null +++ b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/components/BarbellMenuComponent.kt @@ -0,0 +1,52 @@ +/* + * 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.customizebarbells.components + +import androidx.compose.material.DropdownMenu +import androidx.compose.material.DropdownMenuItem +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import com.ankitsuda.rebound.ui.customizebarbells.R + +@Composable +internal fun BarbellMenuComponent( + modifier: Modifier = Modifier, + expanded: Boolean, + onDismissRequest: () -> Unit, + onEditBarbell: () -> Unit, + onDeleteBarbell: () -> Unit, +) { + + DropdownMenu( + modifier = modifier, + expanded = expanded, + onDismissRequest = onDismissRequest + ) { + DropdownMenuItem(onClick = { + onDismissRequest() + onEditBarbell() + }) { + Text(stringResource(R.string.edit)) + } + DropdownMenuItem(onClick = { + onDismissRequest() + onDeleteBarbell() + }) { + Text(stringResource(id = R.string.delete)) + } + } +} \ No newline at end of file diff --git a/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/edit/BarbellEditBottomSheet.kt b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/edit/BarbellEditBottomSheet.kt new file mode 100644 index 00000000..f3f65569 --- /dev/null +++ b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/edit/BarbellEditBottomSheet.kt @@ -0,0 +1,195 @@ +/* + * 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.customizebarbells.edit + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import com.ankitsuda.navigation.LocalNavigator +import com.ankitsuda.navigation.Navigator +import com.ankitsuda.rebound.ui.components.* +import com.ankitsuda.rebound.ui.customizebarbells.R + +@Composable +fun BarbellEditBottomSheet( + navigator: Navigator = LocalNavigator.current, + viewModel: BarbellEditBottomSheetViewModel = hiltViewModel() +) { + val nameFieldValue by viewModel.nameFieldValue.collectAsState() + val weightKgFieldValue by viewModel.weightKgFieldValue.collectAsState() + val weightLbsFieldValue by viewModel.weightLbsFieldValue.collectAsState() + val isUpdate = viewModel.isUpdate + + BarbellEditBottomSheetLayout( + nameFieldValue = nameFieldValue, + weightKgFieldValue = weightKgFieldValue, + weightLbsFieldValue = weightLbsFieldValue, + isUpdate = isUpdate, + isSaveBtnEnabled = nameFieldValue.isNotBlank() && + weightKgFieldValue.isNotBlank() && + weightLbsFieldValue.isNotBlank(), + onChangeNameFieldValue = { + viewModel.updateNameFieldValue(it) + }, + onChangeWeightKgFieldValue = { + viewModel.updateWeightKgFieldValue(it) + }, + onChangeWeightLbsFieldValue = { + viewModel.updateWeightLbsFieldValue(it) + }, + onDelete = { + viewModel.deleteBarbell { + navigator.goBack() + } + }, + onSave = { + viewModel.saveBarbell { + navigator.goBack() + } + } + ) +} + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +private fun BarbellEditBottomSheetLayout( + nameFieldValue: String, + weightKgFieldValue: String, + weightLbsFieldValue: String, + isUpdate: Boolean, + isSaveBtnEnabled: Boolean, + onChangeNameFieldValue: (String) -> Unit, + onChangeWeightKgFieldValue: (String) -> Unit, + onChangeWeightLbsFieldValue: (String) -> Unit, + onDelete: () -> Unit, + onSave: () -> Unit +) { + + val keyboard = LocalSoftwareKeyboardController.current + + BottomSheetSurface { + + Column( + Modifier + .fillMaxWidth() + .navigationBarsPadding() + ) { + + TopBar( + title = stringResource(R.string.barbell), + statusBarEnabled = false, + elevationEnabled = false + ) + + + Column( + modifier = Modifier + .fillMaxWidth() + .padding( + start = 16.dp, + end = 16.dp, + bottom = 16.dp, + top = 8.dp + ), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + + AppTextField( + modifier = Modifier, + value = nameFieldValue, + labelValue = stringResource(R.string.name), + singleLine = true, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Sentences, + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Next, + ), + onValueChange = onChangeNameFieldValue + ) + AppTextField( + modifier = Modifier, + value = weightKgFieldValue, + labelValue = stringResource(R.string.weight_kg), + singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Decimal, + imeAction = ImeAction.Next, + ), + onValueChange = onChangeWeightKgFieldValue + ) + AppTextField( + modifier = Modifier, + value = weightLbsFieldValue, + labelValue = stringResource(R.string.weight_lbs), + singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Decimal, + imeAction = ImeAction.Done, + ), + keyboardActions = KeyboardActions( + onDone = { + if (isSaveBtnEnabled) { + onSave() + } else { + keyboard?.hide() + } + } + ), + onValueChange = onChangeWeightLbsFieldValue + ) + } + + Row( + Modifier + .padding(end = 16.dp, start = 16.dp, bottom = 16.dp) + .align(Alignment.End) + ) { + BottomSheetSecondaryRButton( + modifier = Modifier.padding(end = 16.dp), + onClick = { + onDelete() + }) { + Text(if (isUpdate) stringResource(R.string.delete) else stringResource(R.string.cancel)) + } + + + BottomSheetRButton( + enabled = isSaveBtnEnabled, + onClick = { + onSave() + }, + modifier = Modifier.width(88.dp) + ) { + Text(if (isUpdate) stringResource(R.string.save) else stringResource(R.string.add)) + } + + } + } + } +} \ No newline at end of file diff --git a/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/edit/BarbellEditBottomSheetViewModel.kt b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/edit/BarbellEditBottomSheetViewModel.kt new file mode 100644 index 00000000..6e307000 --- /dev/null +++ b/modules/ui-customize-barbells/src/main/java/com/ankitsuda/rebound/ui/customizebarbells/edit/BarbellEditBottomSheetViewModel.kt @@ -0,0 +1,114 @@ +/* + * 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.customizebarbells.edit + +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.ankitsuda.base.util.toReadableString +import com.ankitsuda.base.utils.generateId +import com.ankitsuda.navigation.BARBELL_ID_KEY +import com.ankitsuda.rebound.data.repositories.BarbellsRepository +import com.ankitsuda.rebound.domain.entities.Barbell +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import java.time.LocalDateTime +import javax.inject.Inject + +@HiltViewModel +class BarbellEditBottomSheetViewModel @Inject constructor( + handle: SavedStateHandle, + private val barbellsRepository: BarbellsRepository +) : ViewModel() { + private val barbellId = handle.get(BARBELL_ID_KEY) + + private var _barbell = MutableStateFlow(null) + val barbell = _barbell.asStateFlow() + + private var _nameFieldValue = MutableStateFlow("") + val nameFieldValue = _nameFieldValue.asStateFlow() + + private var _weightKgFieldValue = MutableStateFlow("") + val weightKgFieldValue = _weightKgFieldValue.asStateFlow() + + private var _weightLbsFieldValue = MutableStateFlow("") + val weightLbsFieldValue = _weightLbsFieldValue.asStateFlow() + + val isUpdate = barbellId != null + + init { + if (barbellId != null) { + viewModelScope.launch { + val mBarbell = barbellsRepository.getBarbell(barbellId).first() + + _nameFieldValue.value = mBarbell.name ?: "" + _weightKgFieldValue.value = mBarbell.weightKg?.toReadableString() ?: "" + _weightLbsFieldValue.value = mBarbell.weightLbs?.toReadableString() ?: "" + + _barbell.value = mBarbell + } + } + } + + fun updateNameFieldValue(value: String) { + _nameFieldValue.value = value + } + + fun updateWeightKgFieldValue(value: String) { + if (value.isEmpty() || value.toDoubleOrNull() != null) { + _weightKgFieldValue.value = value + } + } + + fun updateWeightLbsFieldValue(value: String) { + if (value.isEmpty() || value.toDoubleOrNull() != null) { + _weightLbsFieldValue.value = value + } + } + + fun deleteBarbell(onDeleted: () -> Unit) { + viewModelScope.launch { + _barbell.value?.id?.let { + barbellsRepository.deleteBarbell(it) + } + onDeleted() + } + } + + fun saveBarbell(onSaved: () -> Unit) { + viewModelScope.launch { + val time = LocalDateTime.now() + val lastBarbell = (_barbell.value ?: Barbell( + id = generateId(), + isActive = true, + createdAt = time, + )) + + val mBarbell = lastBarbell.copy( + name = _nameFieldValue.value.takeIf { it.isNotBlank() } ?: lastBarbell.name, + weightKg = _weightKgFieldValue.value.toDoubleOrNull() ?: lastBarbell.weightKg, + weightLbs = _weightLbsFieldValue.value.toDoubleOrNull() ?: lastBarbell.weightLbs, + updatedAt = time + ) + + barbellsRepository.upsertBarbell(mBarbell) + + onSaved() + } + } +} \ No newline at end of file diff --git a/modules/ui-settings/src/main/java/com/ankitsuda/rebound/ui/settings/SettingsScreen.kt b/modules/ui-settings/src/main/java/com/ankitsuda/rebound/ui/settings/SettingsScreen.kt index 1a711513..14f761c1 100644 --- a/modules/ui-settings/src/main/java/com/ankitsuda/rebound/ui/settings/SettingsScreen.kt +++ b/modules/ui-settings/src/main/java/com/ankitsuda/rebound/ui/settings/SettingsScreen.kt @@ -38,6 +38,7 @@ import com.ankitsuda.rebound.ui.components.MoreSectionHeader import com.ankitsuda.rebound.ui.components.TopBar2 import com.ankitsuda.rebound.ui.components.TopBarBackIconButton import com.ankitsuda.rebound.ui.components.settings.PopupItemsSettingsItem +import com.ankitsuda.rebound.ui.icons.Barbell import com.ankitsuda.rebound.ui.icons.Plates import me.onebone.toolbar.CollapsingToolbarScaffold import me.onebone.toolbar.ScrollStrategy @@ -102,6 +103,17 @@ fun SettingsScreen( navigator.navigate(LeafScreen.Plates().createRoute()) }) } + item { + MoreItemCard( + modifier = Modifier + .fillMaxWidth(), + icon = Icons.Filled.Barbell, + text = stringResource(R.string.barbells), + description = stringResource(R.string.customize_barbells), + onClick = { + navigator.navigate(LeafScreen.Barbells().createRoute()) + }) + } item { MoreSectionHeader(text = stringResource(R.string.defaults)) } diff --git a/settings.gradle b/settings.gradle index b560cd9e..ecd920b1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -54,3 +54,4 @@ include ':modules:ui-workout-edit' include ':modules:ui-keyboard' include ':modules:ui-customize-plates' include ':modules:common-ui-components-number-picker' +include ':modules:ui-customize-barbells' diff --git a/svgs/barbell.svg b/svgs/barbell.svg new file mode 100644 index 00000000..3820bdcc --- /dev/null +++ b/svgs/barbell.svg @@ -0,0 +1,5 @@ + + + + +