commit 48e1b41a97816706ad4f3064025fdf3f357f51f0 Author: Paul-1108 Date: Sat May 16 23:23:44 2026 +0200 Initial walking skeleton implementation diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..082f2ed --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Workout Timer \ No newline at end of file diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..4a53bee --- /dev/null +++ b/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..7643783 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,123 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..a4adc75 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/deviceManager.xml b/.idea/deviceManager.xml new file mode 100644 index 0000000..91f9558 --- /dev/null +++ b/.idea/deviceManager.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..cdbc250 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..74dd639 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..34d0f6c --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,70 @@ +# Gradle +.gradle/ +build/ +*/build/ + +# Local configuration +local.properties + +# Android Studio / IntelliJ +.idea/ +*.iml + +# Generated files +captures/ +.externalNativeBuild/ +.cxx/ + +# Kotlin +*.kotlin_module + +# Logs +*.log + +# OS files +.DS_Store +Thumbs.db + +# Keystore files +*.jks +*.keystore + +# Android profiling +*.hprof + +# Temporary files +tmp/ +temp/ + +# APK / Bundle outputs +*.apk +*.aab + +# Emulator / device files +*.lock + +# Navigation editor temp files +.navigation/ + +# Generated folders +bin/ +out/ + +# Mac +.AppleDouble +.LSOverride + +# Windows +ehthumbs.db +Desktop.ini + +# VSCode +.vscode/ + +# JetBrains cache +.idea/caches/ +.idea/libraries/ +.idea/modules.xml +.idea/workspace.xml +.idea/navEditor.xml +.idea/assetWizardSettings.xml \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..ee2105a --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,47 @@ +plugins { + alias(libs.plugins.android.application) +} + +android { + namespace = "com.example.workouttimer" + compileSdk { + version = release(36) { + minorApiLevel = 1 + } + } + + defaultConfig { + applicationId = "com.example.workouttimer" + minSdk = 26 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } +} + +dependencies { + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) + implementation(libs.material) + implementation(libs.androidx.activity) + implementation(libs.androidx.constraintlayout) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/example/workouttimer/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/example/workouttimer/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..5a2ad21 --- /dev/null +++ b/app/src/androidTest/java/com/example/workouttimer/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.example.workouttimer + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.example.workouttimer", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8906cea --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/MainActivity.kt b/app/src/main/java/com/example/workouttimer/MainActivity.kt new file mode 100644 index 0000000..adf3b42 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/MainActivity.kt @@ -0,0 +1,17 @@ +package com.example.workouttimer + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.example.workouttimer.ui.navigation.AppNavigation + +class MainActivity : AppCompatActivity() { + + private lateinit var appNavigation: AppNavigation + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + appNavigation = AppNavigation(this) + setContentView(appNavigation.createContent()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/data/MockWorkoutRepository.kt b/app/src/main/java/com/example/workouttimer/data/MockWorkoutRepository.kt new file mode 100644 index 0000000..01d9429 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/data/MockWorkoutRepository.kt @@ -0,0 +1,38 @@ +package com.example.workouttimer.data + +import com.example.workouttimer.domain.Exercise +import com.example.workouttimer.domain.ExerciseTarget +import com.example.workouttimer.domain.Workout + +class MockWorkoutRepository { + + fun getWorkouts(): List { + return listOf( + Workout( + id = 1, + name = "Full Body Basic", + tags = listOf("Ganzkörper", "Einsteiger"), + exercises = listOf( + Exercise( + id = 1, + name = "Push-ups", + target = ExerciseTarget.Repetitions(12), + info = "Saubere Ausführung, kontrollierte Bewegung." + ), + Exercise( + id = 2, + name = "Plank", + target = ExerciseTarget.Duration(30), + info = "Körper gerade halten." + ), + Exercise( + id = 3, + name = "Squats", + target = ExerciseTarget.Repetitions(15), + info = "Knie stabil halten." + ) + ) + ) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/domain/Exercise.kt b/app/src/main/java/com/example/workouttimer/domain/Exercise.kt new file mode 100644 index 0000000..e216af0 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/domain/Exercise.kt @@ -0,0 +1,8 @@ +package com.example.workouttimer.domain + +data class Exercise( + val id: Int, + val name: String, + val target: ExerciseTarget, + val info: String = "" +) \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/domain/ExerciseTarget.kt b/app/src/main/java/com/example/workouttimer/domain/ExerciseTarget.kt new file mode 100644 index 0000000..ebaec26 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/domain/ExerciseTarget.kt @@ -0,0 +1,8 @@ +package com.example.workouttimer.domain + +sealed class ExerciseTarget { + + data class Repetitions(val reps: Int) : ExerciseTarget() + + data class Duration(val seconds: Int) : ExerciseTarget() +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/domain/Workout.kt b/app/src/main/java/com/example/workouttimer/domain/Workout.kt new file mode 100644 index 0000000..2a16249 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/domain/Workout.kt @@ -0,0 +1,8 @@ +package com.example.workouttimer.domain + +data class Workout( + val id: Int, + val name: String, + val exercises: List, + val tags: List = emptyList() +) \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/domain/WorkoutState.kt b/app/src/main/java/com/example/workouttimer/domain/WorkoutState.kt new file mode 100644 index 0000000..c03d876 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/domain/WorkoutState.kt @@ -0,0 +1,8 @@ +package com.example.workouttimer.domain + +enum class WorkoutState { + READY, + RUNNING, + PAUSED, + FINISHED +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/navigation/AppNavigation.kt b/app/src/main/java/com/example/workouttimer/ui/navigation/AppNavigation.kt new file mode 100644 index 0000000..a1af1c5 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/navigation/AppNavigation.kt @@ -0,0 +1,115 @@ +package com.example.workouttimer.ui.navigation + +import android.content.Context +import android.view.View +import android.widget.FrameLayout +import com.example.workouttimer.ui.screens.FinishedScreen +import com.example.workouttimer.ui.screens.HomeScreen +import com.example.workouttimer.ui.screens.PauseScreen +import com.example.workouttimer.ui.screens.ReadyToStartScreen +import com.example.workouttimer.ui.screens.RunningWorkoutScreen +import com.example.workouttimer.ui.screens.SavedWorkoutsScreen +import com.example.workouttimer.viewmodel.WorkoutViewModel + +class AppNavigation(private val context: Context) { + + private val container = FrameLayout(context) + private val viewModel = WorkoutViewModel() + + fun createContent(): FrameLayout { + showHome() + return container + } + + private fun setScreen(view: View) { + container.removeAllViews() + container.addView(view) + } + + fun showHome() { + setScreen( + HomeScreen( + context = context, + onShowWorkouts = { showSavedWorkouts() } + ) + ) + } + + fun showSavedWorkouts() { + setScreen( + SavedWorkoutsScreen( + context = context, + workouts = viewModel.workouts, + onWorkoutSelected = { workout -> + viewModel.selectWorkout(workout) + showReadyToStart() + }, + onBack = { showHome() } + ) + ) + } + + fun showReadyToStart() { + setScreen( + ReadyToStartScreen( + context = context, + workout = viewModel.currentWorkout, + onStart = { + viewModel.startWorkout() + showRunningWorkout() + }, + onBack = { showSavedWorkouts() } + ) + ) + } + + fun showRunningWorkout() { + setScreen( + RunningWorkoutScreen( + context = context, + workout = viewModel.currentWorkout, + exercise = viewModel.getCurrentExercise(), + exerciseNumber = viewModel.currentExerciseIndex + 1, + onNextExercise = { + viewModel.nextExercise() + + if (viewModel.workoutState.name == "FINISHED") { + showFinished() + } else { + showRunningWorkout() + } + }, + onPause = { + viewModel.pauseWorkout() + showPause() + } + ) + ) + } + + fun showPause() { + setScreen( + PauseScreen( + context = context, + onResume = { + viewModel.resumeWorkout() + showRunningWorkout() + }, + onFinish = { + viewModel.finishWorkout() + showFinished() + } + ) + ) + } + + fun showFinished() { + setScreen( + FinishedScreen( + context = context, + workout = viewModel.currentWorkout, + onBackHome = { showHome() } + ) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/ChooseBreak.kt b/app/src/main/java/com/example/workouttimer/ui/screens/ChooseBreak.kt new file mode 100644 index 0000000..670e6ce --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/ChooseBreak.kt @@ -0,0 +1,4 @@ +package com.example.workouttimer.ui.screens + +class ChooseBreak { +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/ChooseExercise.kt b/app/src/main/java/com/example/workouttimer/ui/screens/ChooseExercise.kt new file mode 100644 index 0000000..ba0b40a --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/ChooseExercise.kt @@ -0,0 +1,4 @@ +package com.example.workouttimer.ui.screens + +class ChooseExercise { +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/ChooseReps.kt b/app/src/main/java/com/example/workouttimer/ui/screens/ChooseReps.kt new file mode 100644 index 0000000..1ede305 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/ChooseReps.kt @@ -0,0 +1,4 @@ +package com.example.workouttimer.ui.screens + +class ChooseReps { +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/CreateOrModifyScreen.kt b/app/src/main/java/com/example/workouttimer/ui/screens/CreateOrModifyScreen.kt new file mode 100644 index 0000000..3f37de1 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/CreateOrModifyScreen.kt @@ -0,0 +1,4 @@ +package com.example.workouttimer.ui.screens + +class CreateOrModifyScreen { +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/FinishedScreen.kt b/app/src/main/java/com/example/workouttimer/ui/screens/FinishedScreen.kt new file mode 100644 index 0000000..0313f9d --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/FinishedScreen.kt @@ -0,0 +1,47 @@ +package com.example.workouttimer.ui.screens + +import android.content.Context +import android.view.Gravity +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView +import com.example.workouttimer.domain.Workout + +class FinishedScreen( + context: Context, + workout: Workout?, + onBackHome: () -> Unit +) : LinearLayout(context) { + + init { + orientation = VERTICAL + gravity = Gravity.CENTER + setPadding(48, 48, 48, 48) + + val title = TextView(context) + title.text = "Workout beendet!" + title.textSize = 32f + title.gravity = Gravity.CENTER + + val workoutText = TextView(context) + workoutText.text = workout?.name ?: "" + workoutText.textSize = 22f + workoutText.gravity = Gravity.CENTER + + val summary = TextView(context) + summary.text = "Gute Arbeit. Dein Workout wurde erfolgreich abgeschlossen." + summary.textSize = 18f + summary.gravity = Gravity.CENTER + + val homeButton = Button(context) + homeButton.text = "Zur Startseite" + homeButton.setOnClickListener { + onBackHome() + } + + addView(title) + addView(workoutText) + addView(summary) + addView(homeButton) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/HomeScreen.kt b/app/src/main/java/com/example/workouttimer/ui/screens/HomeScreen.kt new file mode 100644 index 0000000..a50228a --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/HomeScreen.kt @@ -0,0 +1,39 @@ +package com.example.workouttimer.ui.screens + +import android.content.Context +import android.view.Gravity +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView + +class HomeScreen( + context: Context, + onShowWorkouts: () -> Unit +) : LinearLayout(context) { + + init { + orientation = VERTICAL + gravity = Gravity.CENTER + setPadding(48, 48, 48, 48) + + val title = TextView(context) + title.text = "Workout Timer" + title.textSize = 32f + title.gravity = Gravity.CENTER + + val subtitle = TextView(context) + subtitle.text = "Plane und starte dein Workout" + subtitle.textSize = 18f + subtitle.gravity = Gravity.CENTER + + val button = Button(context) + button.text = "Gespeicherte Workouts" + button.setOnClickListener { + onShowWorkouts() + } + + addView(title) + addView(subtitle) + addView(button) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/PauseScreen.kt b/app/src/main/java/com/example/workouttimer/ui/screens/PauseScreen.kt new file mode 100644 index 0000000..1fbac3f --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/PauseScreen.kt @@ -0,0 +1,41 @@ +package com.example.workouttimer.ui.screens + +import android.content.Context +import android.view.Gravity +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView + +class PauseScreen( + context: Context, + onResume: () -> Unit, + onFinish: () -> Unit +) : LinearLayout(context) { + + init { + orientation = VERTICAL + gravity = Gravity.CENTER + setPadding(48, 48, 48, 48) + + val title = TextView(context) + title.text = "Pause" + title.textSize = 32f + title.gravity = Gravity.CENTER + + val resumeButton = Button(context) + resumeButton.text = "Weiter trainieren" + resumeButton.setOnClickListener { + onResume() + } + + val finishButton = Button(context) + finishButton.text = "Workout beenden" + finishButton.setOnClickListener { + onFinish() + } + + addView(title) + addView(resumeButton) + addView(finishButton) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/ReadyToStartScreen.kt b/app/src/main/java/com/example/workouttimer/ui/screens/ReadyToStartScreen.kt new file mode 100644 index 0000000..ea487a3 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/ReadyToStartScreen.kt @@ -0,0 +1,59 @@ +package com.example.workouttimer.ui.screens + +import android.content.Context +import android.view.Gravity +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView +import com.example.workouttimer.domain.ExerciseTarget +import com.example.workouttimer.domain.Workout + +class ReadyToStartScreen( + context: Context, + workout: Workout?, + onStart: () -> Unit, + onBack: () -> Unit +) : LinearLayout(context) { + + init { + orientation = VERTICAL + gravity = Gravity.CENTER_HORIZONTAL + setPadding(48, 48, 48, 48) + + val title = TextView(context) + title.text = workout?.name ?: "Kein Workout ausgewählt" + title.textSize = 28f + title.gravity = Gravity.CENTER + + addView(title) + + workout?.exercises?.forEach { exercise -> + val exerciseText = TextView(context) + exerciseText.text = "${exercise.name} - ${formatTarget(exercise.target)}" + exerciseText.textSize = 18f + addView(exerciseText) + } + + val startButton = Button(context) + startButton.text = "Workout starten" + startButton.setOnClickListener { + onStart() + } + + val backButton = Button(context) + backButton.text = "Zurück" + backButton.setOnClickListener { + onBack() + } + + addView(startButton) + addView(backButton) + } + + private fun formatTarget(target: ExerciseTarget): String { + return when (target) { + is ExerciseTarget.Repetitions -> "${target.reps} Wiederholungen" + is ExerciseTarget.Duration -> "${target.seconds} Sekunden" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/RunningWorkoutScreen.kt b/app/src/main/java/com/example/workouttimer/ui/screens/RunningWorkoutScreen.kt new file mode 100644 index 0000000..a704857 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/RunningWorkoutScreen.kt @@ -0,0 +1,72 @@ +package com.example.workouttimer.ui.screens + +import android.content.Context +import android.view.Gravity +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView +import com.example.workouttimer.domain.Exercise +import com.example.workouttimer.domain.ExerciseTarget +import com.example.workouttimer.domain.Workout + +class RunningWorkoutScreen( + context: Context, + workout: Workout?, + exercise: Exercise?, + exerciseNumber: Int, + onNextExercise: () -> Unit, + onPause: () -> Unit +) : LinearLayout(context) { + + init { + orientation = VERTICAL + gravity = Gravity.CENTER + setPadding(48, 48, 48, 48) + + val workoutTitle = TextView(context) + workoutTitle.text = workout?.name ?: "Workout läuft" + workoutTitle.textSize = 22f + workoutTitle.gravity = Gravity.CENTER + + val exerciseTitle = TextView(context) + exerciseTitle.text = "Übung $exerciseNumber: ${exercise?.name ?: "-"}" + exerciseTitle.textSize = 30f + exerciseTitle.gravity = Gravity.CENTER + + val targetText = TextView(context) + targetText.text = exercise?.target?.let { formatTarget(it) } ?: "" + targetText.textSize = 24f + targetText.gravity = Gravity.CENTER + + val infoText = TextView(context) + infoText.text = exercise?.info ?: "" + infoText.textSize = 16f + infoText.gravity = Gravity.CENTER + + val nextButton = Button(context) + nextButton.text = "Übung geschafft / Weiter" + nextButton.setOnClickListener { + onNextExercise() + } + + val pauseButton = Button(context) + pauseButton.text = "Pause" + pauseButton.setOnClickListener { + onPause() + } + + addView(workoutTitle) + addView(exerciseTitle) + addView(targetText) + addView(infoText) + addView(nextButton) + addView(pauseButton) + } + + private fun formatTarget(target: ExerciseTarget): String { + return when (target) { + is ExerciseTarget.Repetitions -> "${target.reps} Wiederholungen" + is ExerciseTarget.Duration -> "${target.seconds} Sekunden" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/SaveWorkoutScreen.kt b/app/src/main/java/com/example/workouttimer/ui/screens/SaveWorkoutScreen.kt new file mode 100644 index 0000000..44f110c --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/SaveWorkoutScreen.kt @@ -0,0 +1,4 @@ +package com.example.workouttimer.ui.screens + +class SaveWorkoutScreen { +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/ui/screens/SavedWorkoutsScreen.kt b/app/src/main/java/com/example/workouttimer/ui/screens/SavedWorkoutsScreen.kt new file mode 100644 index 0000000..a0f9a01 --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/ui/screens/SavedWorkoutsScreen.kt @@ -0,0 +1,46 @@ +package com.example.workouttimer.ui.screens + +import android.content.Context +import android.view.Gravity +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView +import com.example.workouttimer.domain.Workout + +class SavedWorkoutsScreen( + context: Context, + workouts: List, + onWorkoutSelected: (Workout) -> Unit, + onBack: () -> Unit +) : LinearLayout(context) { + + init { + orientation = VERTICAL + gravity = Gravity.CENTER_HORIZONTAL + setPadding(48, 48, 48, 48) + + val title = TextView(context) + title.text = "Gespeicherte Workouts" + title.textSize = 28f + title.gravity = Gravity.CENTER + + addView(title) + + workouts.forEach { workout -> + val workoutButton = Button(context) + workoutButton.text = workout.name + workoutButton.setOnClickListener { + onWorkoutSelected(workout) + } + addView(workoutButton) + } + + val backButton = Button(context) + backButton.text = "Zurück" + backButton.setOnClickListener { + onBack() + } + + addView(backButton) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/workouttimer/viewmodel/WorkoutViewModel.kt b/app/src/main/java/com/example/workouttimer/viewmodel/WorkoutViewModel.kt new file mode 100644 index 0000000..e3f186a --- /dev/null +++ b/app/src/main/java/com/example/workouttimer/viewmodel/WorkoutViewModel.kt @@ -0,0 +1,62 @@ +package com.example.workouttimer.viewmodel + +import com.example.workouttimer.data.MockWorkoutRepository +import com.example.workouttimer.domain.Exercise +import com.example.workouttimer.domain.Workout +import com.example.workouttimer.domain.WorkoutState + +class WorkoutViewModel { + + private val repository = MockWorkoutRepository() + + val workouts: List = repository.getWorkouts() + + var currentWorkout: Workout? = null + private set + + var currentExerciseIndex = 0 + private set + + var workoutState = WorkoutState.READY + private set + + fun selectWorkout(workout: Workout) { + currentWorkout = workout + currentExerciseIndex = 0 + workoutState = WorkoutState.READY + } + + fun startWorkout() { + workoutState = WorkoutState.RUNNING + } + + fun pauseWorkout() { + workoutState = WorkoutState.PAUSED + } + + fun resumeWorkout() { + workoutState = WorkoutState.RUNNING + } + + fun finishWorkout() { + workoutState = WorkoutState.FINISHED + } + + fun nextExercise() { + + val workout = currentWorkout ?: return + + if (currentExerciseIndex < workout.exercises.lastIndex) { + currentExerciseIndex++ + } else { + finishWorkout() + } + } + + fun getCurrentExercise(): Exercise? { + + val workout = currentWorkout ?: return null + + return workout.exercises[currentExerciseIndex] + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..86a5d97 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/app/src/main/res/mipmap-anydpi/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..918c936 --- /dev/null +++ b/app/src/main/res/values-night/themes.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..c8524cd --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..ffc03bc --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Workout Timer + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..ced67fa --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,9 @@ + + + + +