Răsfoiți Sursa

Add the UI for the main page and the new workout page.

Lee Morgan 3 săptămâni în urmă
părinte
comite
aeb233af7e

+ 13 - 0
.idea/deviceManager.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="DeviceTable">
+    <option name="columnSorters">
+      <list>
+        <ColumnSorterState>
+          <option name="column" value="Name" />
+          <option name="order" value="ASCENDING" />
+        </ColumnSorterState>
+      </list>
+    </option>
+  </component>
+</project>

+ 3 - 0
Agents.md → AGENTS.md

@@ -1,3 +1,6 @@
+# App Description
+This is meant to be an exercise application for all sorts of exercise. It will primarily store data locally. Storing to a database will be an optional upgrade. One of the big purposes of this is to avoid the garbage apps that have tons of ads and other stuff. Nice and simple and easy to use for any type of exercise.
+
 # Style
 
 Dark only. Surfaces stay quiet so effort reads as heat. Prefer borders over shadows.

+ 86 - 0
app/src/androidTest/java/com/example/torus/HomeScreenTest.kt

@@ -0,0 +1,86 @@
+package com.example.torus
+
+import androidx.compose.ui.test.assertCountEquals
+import androidx.compose.ui.test.assertDoesNotExist
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.hasClickAction
+import androidx.compose.ui.test.hasText
+import androidx.compose.ui.test.junit4.createAndroidComposeRule
+import androidx.compose.ui.test.onAllNodesWithText
+import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import org.junit.Rule
+import org.junit.Test
+
+class HomeScreenTest {
+    @get:Rule
+    val composeTestRule = createAndroidComposeRule<MainActivity>()
+
+    @Test
+    fun homeScreen_displaysLogoAndTitle() {
+        composeTestRule.onNodeWithText("Torus").assertIsDisplayed()
+        composeTestRule.onNodeWithContentDescription("Torus logo").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Add exercise").assertIsDisplayed()
+    }
+
+    @Test
+    fun addExercise_opensCreateWorkoutPage() {
+        composeTestRule.onNodeWithText("Add exercise").performClick()
+        composeTestRule.onNodeWithText("Create Workout").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Save Workout").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Torus").assertIsDisplayed()
+        composeTestRule.onNodeWithContentDescription("Torus logo").assertIsDisplayed()
+    }
+
+    @Test
+    fun headerClick_returnsToHome() {
+        composeTestRule.onNodeWithText("Add exercise").performClick()
+        composeTestRule.onNodeWithText("Create Workout").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Torus").performClick()
+        composeTestRule.onNodeWithText("Add exercise").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Create Workout").assertDoesNotExist()
+    }
+
+    @Test
+    fun createWorkout_showsNameFieldAndExerciseTypes() {
+        composeTestRule.onNodeWithText("Add exercise").performClick()
+        composeTestRule.onNodeWithText("Workout name").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Weights").assertDoesNotExist()
+        composeTestRule.onNodeWithText("Add exercise").performClick()
+        composeTestRule.onNodeWithText("What type of exercise?").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Weights").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Run").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Weights").performClick()
+        composeTestRule.onNodeWithText("Create Workout").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Exercise name").assertIsDisplayed()
+        composeTestRule.onNodeWithText("1").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Add exercise").assertIsDisplayed()
+        composeTestRule.onNodeWithText("What type of exercise?").assertDoesNotExist()
+    }
+
+    @Test
+    fun createWorkout_canAddAnotherWeightsExercise() {
+        composeTestRule.onNodeWithText("Add exercise").performClick()
+        composeTestRule.onNodeWithText("Add exercise").performClick()
+        composeTestRule.onNodeWithText("Weights").performClick()
+        composeTestRule.onNodeWithText("Add exercise").performClick()
+        composeTestRule.onNode(hasText("Weights") and hasClickAction()).performClick()
+        composeTestRule.onAllNodesWithText("Exercise name").assertCountEquals(2)
+        composeTestRule.onNodeWithText("1").assertIsDisplayed()
+        composeTestRule.onNodeWithText("2").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Add exercise").assertIsDisplayed()
+    }
+
+    @Test
+    fun createWorkout_addsRunExercise() {
+        composeTestRule.onNodeWithText("Add exercise").performClick()
+        composeTestRule.onNodeWithText("Add exercise").performClick()
+        composeTestRule.onNodeWithText("Run").performClick()
+        composeTestRule.onNodeWithText("Run").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Exercise name").assertIsDisplayed()
+        composeTestRule.onNodeWithText("1").assertIsDisplayed()
+        composeTestRule.onNodeWithText("Add exercise").assertIsDisplayed()
+        composeTestRule.onNodeWithText("What type of exercise?").assertDoesNotExist()
+    }
+}

+ 2 - 29
app/src/main/java/com/example/torus/MainActivity.kt

@@ -4,13 +4,7 @@ import android.os.Bundle
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.activity.enableEdgeToEdge
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material3.Scaffold
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.tooling.preview.Preview
+import com.example.torus.ui.TorusApp
 import com.example.torus.ui.theme.TorusTheme
 
 class MainActivity : ComponentActivity() {
@@ -19,29 +13,8 @@ class MainActivity : ComponentActivity() {
         enableEdgeToEdge()
         setContent {
             TorusTheme {
-                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
-                    Greeting(
-                        name = "Penis Butthole Dude",
-                        modifier = Modifier.padding(innerPadding)
-                    )
-                }
+                TorusApp()
             }
         }
     }
 }
-
-@Composable
-fun Greeting(name: String, modifier: Modifier = Modifier) {
-    Text(
-        text = "Hello $name!",
-        modifier = modifier
-    )
-}
-
-@Preview(showBackground = true)
-@Composable
-fun GreetingPreview() {
-    TorusTheme {
-        Greeting("Android")
-    }
-}

+ 56 - 0
app/src/main/java/com/example/torus/ui/AppHeader.kt

@@ -0,0 +1,56 @@
+package com.example.torus.ui
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import com.example.torus.R
+
+@Composable
+fun AppHeader(
+    modifier: Modifier = Modifier,
+    onClick: () -> Unit = {}
+) {
+    Row(
+        modifier = modifier
+            .fillMaxWidth()
+            .clickable(onClick = onClick)
+            .padding(horizontal = 16.dp, vertical = 12.dp),
+        verticalAlignment = Alignment.CenterVertically,
+        horizontalArrangement = Arrangement.Start
+    ) {
+        Image(
+            painter = painterResource(R.drawable.torus),
+            contentDescription = stringResource(R.string.logo_content_description),
+            modifier = Modifier
+                .size(32.dp)
+                .clip(CircleShape),
+            contentScale = ContentScale.Crop
+        )
+        Spacer(modifier = Modifier.width(10.dp))
+        Text(
+            text = stringResource(R.string.app_name),
+            color = MaterialTheme.colorScheme.onBackground,
+            style = MaterialTheme.typography.titleLarge.copy(
+                fontWeight = FontWeight.SemiBold
+            )
+        )
+    }
+}

+ 277 - 0
app/src/main/java/com/example/torus/ui/CreateWorkoutScreen.kt

@@ -0,0 +1,277 @@
+package com.example.torus.ui
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.OutlinedTextFieldDefaults
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextFieldColors
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.key
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.withFrameNanos
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.example.torus.R
+import com.example.torus.ui.theme.Sand
+import com.example.torus.ui.theme.TorusTheme
+import java.util.UUID
+import kotlinx.coroutines.launch
+
+private enum class ExerciseType {
+    Weights,
+    Run,
+}
+
+private data class DraftExercise(
+    val id: String,
+    val type: ExerciseType,
+    val name: String = "",
+)
+
+@Composable
+fun CreateWorkoutScreen(modifier: Modifier = Modifier) {
+    var workoutName by rememberSaveable { mutableStateOf("") }
+    var showExerciseTypes by rememberSaveable { mutableStateOf(false) }
+    val exercises = remember { mutableStateListOf<DraftExercise>() }
+    val scrollState = rememberScrollState()
+    val coroutineScope = rememberCoroutineScope()
+
+    fun addExercise(type: ExerciseType) {
+        exercises += DraftExercise(id = UUID.randomUUID().toString(), type = type)
+        showExerciseTypes = false
+    }
+
+    Column(modifier = modifier.fillMaxSize()) {
+        Column(
+            modifier = Modifier
+                .weight(1f)
+                .fillMaxWidth()
+                .verticalScroll(scrollState)
+                .padding(horizontal = 16.dp, vertical = 8.dp),
+            verticalArrangement = Arrangement.spacedBy(16.dp)
+        ) {
+            Text(
+                text = stringResource(R.string.create_workout),
+                color = Sand,
+                style = MaterialTheme.typography.headlineMedium
+            )
+            TorusTextField(
+                value = workoutName,
+                onValueChange = { workoutName = it },
+                label = stringResource(R.string.workout_name)
+            )
+            exercises.forEachIndexed { index, exercise ->
+                key(exercise.id) {
+                    NamedExerciseEditor(
+                        number = index + 1,
+                        typeLabel = stringResource(exercise.type.labelRes),
+                        name = exercise.name,
+                        onNameChange = { name ->
+                            val exerciseIndex = exercises.indexOfFirst { it.id == exercise.id }
+                            if (exerciseIndex >= 0) {
+                                exercises[exerciseIndex] = exercises[exerciseIndex].copy(name = name)
+                            }
+                        }
+                    )
+                }
+            }
+            Button(
+                onClick = {
+                    showExerciseTypes = true
+                    coroutineScope.launch {
+                        withFrameNanos { }
+                        withFrameNanos { }
+                        scrollState.animateScrollTo(scrollState.maxValue)
+                    }
+                },
+                shape = RoundedCornerShape(50),
+                colors = ButtonDefaults.buttonColors(
+                    containerColor = MaterialTheme.colorScheme.primary,
+                    contentColor = MaterialTheme.colorScheme.onPrimary
+                )
+            ) {
+                Text(text = stringResource(R.string.add_exercise))
+            }
+            if (showExerciseTypes) {
+                ExerciseTypePicker(
+                    onWeightsClick = { addExercise(ExerciseType.Weights) },
+                    onRunClick = { addExercise(ExerciseType.Run) }
+                )
+            }
+        }
+        Button(
+            onClick = {},
+            modifier = Modifier
+                .fillMaxWidth()
+                .padding(horizontal = 16.dp, vertical = 12.dp),
+            shape = RoundedCornerShape(50),
+            colors = ButtonDefaults.buttonColors(
+                containerColor = MaterialTheme.colorScheme.primary,
+                contentColor = MaterialTheme.colorScheme.onPrimary
+            )
+        ) {
+            Text(text = stringResource(R.string.save_workout))
+        }
+    }
+}
+
+private val ExerciseType.labelRes: Int
+    get() = when (this) {
+        ExerciseType.Weights -> R.string.exercise_type_weights
+        ExerciseType.Run -> R.string.exercise_type_run
+    }
+
+@Composable
+private fun NamedExerciseEditor(
+    number: Int,
+    typeLabel: String,
+    name: String,
+    onNameChange: (String) -> Unit
+) {
+    val shape = RoundedCornerShape(14.dp)
+    Column(
+        modifier = Modifier
+            .fillMaxWidth()
+            .border(1.dp, MaterialTheme.colorScheme.outline, shape)
+            .padding(16.dp),
+        verticalArrangement = Arrangement.spacedBy(12.dp)
+    ) {
+        Row(
+            modifier = Modifier.fillMaxWidth(),
+            horizontalArrangement = Arrangement.SpaceBetween,
+            verticalAlignment = Alignment.CenterVertically
+        ) {
+            Text(
+                text = typeLabel,
+                color = MaterialTheme.colorScheme.onSurfaceVariant,
+                style = MaterialTheme.typography.labelLarge
+            )
+            Text(
+                text = number.toString(),
+                color = MaterialTheme.colorScheme.onSurfaceVariant,
+                style = MaterialTheme.typography.labelSmall
+            )
+        }
+        TorusTextField(
+            value = name,
+            onValueChange = onNameChange,
+            label = stringResource(R.string.exercise_name)
+        )
+    }
+}
+
+@Composable
+private fun ExerciseTypePicker(
+    onWeightsClick: () -> Unit,
+    onRunClick: () -> Unit = {}
+) {
+    val shape = RoundedCornerShape(14.dp)
+    Column(
+        modifier = Modifier
+            .fillMaxWidth()
+            .background(MaterialTheme.colorScheme.surfaceVariant, shape)
+            .border(1.dp, MaterialTheme.colorScheme.primary, shape)
+            .padding(16.dp),
+        verticalArrangement = Arrangement.spacedBy(12.dp)
+    ) {
+        Text(
+            text = stringResource(R.string.choose_exercise_type),
+            color = MaterialTheme.colorScheme.onSurfaceVariant,
+            style = MaterialTheme.typography.titleSmall
+        )
+        ExerciseTypeOption(
+            label = stringResource(R.string.exercise_type_weights),
+            onClick = onWeightsClick
+        )
+        ExerciseTypeOption(
+            label = stringResource(R.string.exercise_type_run),
+            onClick = onRunClick
+        )
+    }
+}
+
+@Composable
+private fun ExerciseTypeOption(
+    label: String,
+    onClick: () -> Unit = {}
+) {
+    OutlinedButton(
+        onClick = onClick,
+        modifier = Modifier.fillMaxWidth(),
+        shape = RoundedCornerShape(50),
+        colors = ButtonDefaults.outlinedButtonColors(
+            contentColor = MaterialTheme.colorScheme.onBackground
+        ),
+        border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant)
+    ) {
+        Text(text = label)
+    }
+}
+
+@Composable
+private fun TorusTextField(
+    value: String,
+    onValueChange: (String) -> Unit,
+    label: String,
+    modifier: Modifier = Modifier
+) {
+    OutlinedTextField(
+        value = value,
+        onValueChange = onValueChange,
+        modifier = modifier.fillMaxWidth(),
+        label = { Text(text = label) },
+        singleLine = true,
+        shape = RoundedCornerShape(14.dp),
+        colors = torusTextFieldColors()
+    )
+}
+
+@Composable
+private fun torusTextFieldColors(): TextFieldColors {
+    return OutlinedTextFieldDefaults.colors(
+        focusedTextColor = MaterialTheme.colorScheme.onBackground,
+        unfocusedTextColor = MaterialTheme.colorScheme.onBackground,
+        focusedBorderColor = MaterialTheme.colorScheme.primary,
+        unfocusedBorderColor = MaterialTheme.colorScheme.outline,
+        focusedLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
+        unfocusedLabelColor = MaterialTheme.colorScheme.onSurfaceVariant,
+        cursorColor = MaterialTheme.colorScheme.primary,
+        focusedContainerColor = MaterialTheme.colorScheme.surface,
+        unfocusedContainerColor = MaterialTheme.colorScheme.surface
+    )
+}
+
+@Preview(showBackground = true, backgroundColor = 0xFF0C0F14)
+@Composable
+private fun CreateWorkoutScreenPreview() {
+    TorusTheme {
+        Column {
+            AppHeader()
+            CreateWorkoutScreen()
+        }
+    }
+}

+ 48 - 0
app/src/main/java/com/example/torus/ui/HomeScreen.kt

@@ -0,0 +1,48 @@
+package com.example.torus.ui
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.example.torus.R
+import com.example.torus.ui.theme.TorusTheme
+
+@Composable
+fun HomeScreen(
+    modifier: Modifier = Modifier,
+    onAddExercise: () -> Unit = {}
+) {
+    Column(modifier = modifier.fillMaxSize()) {
+        Button(
+            onClick = onAddExercise,
+            modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
+            shape = RoundedCornerShape(50),
+            colors = ButtonDefaults.buttonColors(
+                containerColor = MaterialTheme.colorScheme.primary,
+                contentColor = MaterialTheme.colorScheme.onPrimary
+            )
+        ) {
+            Text(text = stringResource(R.string.add_exercise))
+        }
+    }
+}
+
+@Preview(showBackground = true, backgroundColor = 0xFF0C0F14)
+@Composable
+private fun HomeScreenPreview() {
+    TorusTheme {
+        Column {
+            AppHeader()
+            HomeScreen()
+        }
+    }
+}

+ 40 - 0
app/src/main/java/com/example/torus/ui/TorusApp.kt

@@ -0,0 +1,40 @@
+package com.example.torus.ui
+
+import androidx.activity.compose.BackHandler
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Scaffold
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+
+private enum class Screen {
+    Home,
+    CreateWorkout,
+}
+
+@Composable
+fun TorusApp() {
+    var screen by rememberSaveable { mutableStateOf(Screen.Home) }
+
+    BackHandler(enabled = screen != Screen.Home) {
+        screen = Screen.Home
+    }
+
+    Scaffold(
+        modifier = Modifier.fillMaxSize(),
+        topBar = { AppHeader(onClick = { screen = Screen.Home }) }
+    ) { innerPadding ->
+        val contentModifier = Modifier.padding(innerPadding)
+        when (screen) {
+            Screen.Home -> HomeScreen(
+                modifier = contentModifier,
+                onAddExercise = { screen = Screen.CreateWorkout }
+            )
+            Screen.CreateWorkout -> CreateWorkoutScreen(modifier = contentModifier)
+        }
+    }
+}

+ 22 - 7
app/src/main/java/com/example/torus/ui/theme/Color.kt

@@ -2,10 +2,25 @@ package com.example.torus.ui.theme
 
 import androidx.compose.ui.graphics.Color
 
-val Purple80 = Color(0xFFD0BCFF)
-val PurpleGrey80 = Color(0xFFCCC2DC)
-val Pink80 = Color(0xFFEFB8C8)
-
-val Purple40 = Color(0xFF6650a4)
-val PurpleGrey40 = Color(0xFF625b71)
-val Pink40 = Color(0xFF7D5260)
+val InkSunken = Color(0xFF0C0F14)
+val Ink = Color(0xFF12161C)
+val InkRaised = Color(0xFF1B222C)
+val Paper = Color(0xFFF4EFE6)
+val PaperDim = Color(0xFFD8D0C4)
+val Mist = Color(0xFF8B97A8)
+val Line = Color(0xFF2C3542)
+val LineStrong = Color(0xFF3D4A5C)
+val Ember = Color(0xFFE25B3A)
+val EmberDeep = Color(0xFFB84328)
+val EmberSoft = Color(0xFFF3B6A4)
+val EmberOn = Color(0xFF1A0D09)
+val Tide = Color(0xFF3E8F86)
+val TideDeep = Color(0xFF2A6861)
+val TideSoft = Color(0xFFB7D8D4)
+val TideOn = Color(0xFF071614)
+val Sand = Color(0xFFE7C07A)
+val SandDeep = Color(0xFFC4964A)
+val Pulse = Color(0xFFD4526E)
+val Ok = Color(0xFF6EA36A)
+val Warn = Color(0xFFD4A24A)
+val Danger = Color(0xFFC44B4B)

+ 26 - 45
app/src/main/java/com/example/torus/ui/theme/Theme.kt

@@ -1,58 +1,39 @@
 package com.example.torus.ui.theme
 
-import android.app.Activity
-import android.os.Build
-import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.darkColorScheme
-import androidx.compose.material3.dynamicDarkColorScheme
-import androidx.compose.material3.dynamicLightColorScheme
-import androidx.compose.material3.lightColorScheme
 import androidx.compose.runtime.Composable
-import androidx.compose.ui.platform.LocalContext
 
-private val DarkColorScheme = darkColorScheme(
-    primary = Purple80,
-    secondary = PurpleGrey80,
-    tertiary = Pink80
-)
-
-private val LightColorScheme = lightColorScheme(
-    primary = Purple40,
-    secondary = PurpleGrey40,
-    tertiary = Pink40
-
-    /* Other default colors to override
-    background = Color(0xFFFFFBFE),
-    surface = Color(0xFFFFFBFE),
-    onPrimary = Color.White,
-    onSecondary = Color.White,
-    onTertiary = Color.White,
-    onBackground = Color(0xFF1C1B1F),
-    onSurface = Color(0xFF1C1B1F),
-    */
+private val TorusColorScheme = darkColorScheme(
+    primary = Ember,
+    onPrimary = EmberOn,
+    primaryContainer = EmberDeep,
+    onPrimaryContainer = EmberSoft,
+    secondary = Tide,
+    onSecondary = TideOn,
+    secondaryContainer = TideDeep,
+    onSecondaryContainer = TideSoft,
+    tertiary = Sand,
+    onTertiary = EmberOn,
+    tertiaryContainer = SandDeep,
+    onTertiaryContainer = Paper,
+    background = InkSunken,
+    onBackground = Paper,
+    surface = Ink,
+    onSurface = Paper,
+    surfaceVariant = InkRaised,
+    onSurfaceVariant = PaperDim,
+    outline = Line,
+    outlineVariant = LineStrong,
+    error = Danger,
+    onError = Paper,
 )
 
 @Composable
-fun TorusTheme(
-    darkTheme: Boolean = isSystemInDarkTheme(),
-    // Dynamic color is available on Android 12+
-    dynamicColor: Boolean = true,
-    content: @Composable () -> Unit
-) {
-    val colorScheme = when {
-        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
-            val context = LocalContext.current
-            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
-        }
-
-        darkTheme -> DarkColorScheme
-        else -> LightColorScheme
-    }
-
+fun TorusTheme(content: @Composable () -> Unit) {
     MaterialTheme(
-        colorScheme = colorScheme,
+        colorScheme = TorusColorScheme,
         typography = Typography,
         content = content
     )
-}
+}

BIN
app/src/main/res/drawable-nodpi/torus.png


+ 5 - 8
app/src/main/res/values/colors.xml

@@ -1,10 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <color name="purple_200">#FFBB86FC</color>
-    <color name="purple_500">#FF6200EE</color>
-    <color name="purple_700">#FF3700B3</color>
-    <color name="teal_200">#FF03DAC5</color>
-    <color name="teal_700">#FF018786</color>
-    <color name="black">#FF000000</color>
-    <color name="white">#FFFFFFFF</color>
-</resources>
+    <color name="ink_sunken">#FF0C0F14</color>
+    <color name="ink">#FF12161C</color>
+    <color name="paper">#FFF4EFE6</color>
+    <color name="ember">#FFE25B3A</color>
+</resources>

+ 10 - 1
app/src/main/res/values/strings.xml

@@ -1,3 +1,12 @@
 <resources>
     <string name="app_name">Torus</string>
-</resources>
+    <string name="logo_content_description">Torus logo</string>
+    <string name="add_exercise">Add exercise</string>
+    <string name="create_workout">Create Workout</string>
+    <string name="workout_name">Workout name</string>
+    <string name="choose_exercise_type">What type of exercise?</string>
+    <string name="exercise_type_weights">Weights</string>
+    <string name="exercise_type_run">Run</string>
+    <string name="exercise_name">Exercise name</string>
+    <string name="save_workout">Save Workout</string>
+</resources>

+ 6 - 3
app/src/main/res/values/themes.xml

@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-
-    <style name="Theme.Torus" parent="android:Theme.Material.Light.NoActionBar" />
-</resources>
+    <style name="Theme.Torus" parent="android:Theme.Material.NoActionBar">
+        <item name="android:windowBackground">@color/ink_sunken</item>
+        <item name="android:statusBarColor">@color/ink_sunken</item>
+        <item name="android:navigationBarColor">@color/ink_sunken</item>
+    </style>
+</resources>

BIN
res/drawable/torus.png