commit 3933d11751ff63d6c0256711382f40aee3f94230 Author: Martim de Sá Cunha <240411@MacBook-Pro-14.local> Date: Mon Nov 3 11:53:50 2025 +0000 first commit 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..dd75605 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +GymFlow-Martim \ 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/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..b268ef3 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..639c779 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ 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/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..6a5d57c --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,46 @@ +plugins { + alias(libs.plugins.android.application) +} + +android { + namespace = "com.example.gymflow_martim" + compileSdk = 36 + + defaultConfig { + applicationId = "com.example.gymflow_martim" + minSdk = 24 + targetSdk = 34 + 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.appcompat) + implementation(libs.material) + implementation(libs.activity) + implementation(libs.constraintlayout) + implementation(libs.recyclerview) + implementation(libs.cardview) + implementation(libs.coordinatorlayout) + testImplementation(libs.junit) + androidTestImplementation(libs.ext.junit) + androidTestImplementation(libs.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/gymflow_martim/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/gymflow_martim/ExampleInstrumentedTest.java new file mode 100644 index 0000000..19708c1 --- /dev/null +++ b/app/src/androidTest/java/com/example/gymflow_martim/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.example.gymflow_martim; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.example.gymflow_martim", appContext.getPackageName()); + } +} \ 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..2004cd3 --- /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/adapters/ExerciseAdapter.java b/app/src/main/java/adapters/ExerciseAdapter.java new file mode 100644 index 0000000..4e509c1 --- /dev/null +++ b/app/src/main/java/adapters/ExerciseAdapter.java @@ -0,0 +1,89 @@ +package adapters; + +import android.database.Cursor; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.example.gymflow_martim.R; +import models.Exercise; +import models.FeedReaderContract; + +import java.util.ArrayList; +import java.util.List; + +public class ExerciseAdapter extends RecyclerView.Adapter { + + private List exercises = new ArrayList<>(); + private OnItemClickListener listener; + + public interface OnItemClickListener { + void onItemClick(Exercise exercise); + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.listener = listener; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_exercise, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + Exercise exercise = exercises.get(position); + holder.textViewName.setText(exercise.getName()); + holder.textViewSetsReps.setText(exercise.toString()); + } + + @Override + public int getItemCount() { + return exercises.size(); + } + + public void setExercises(Cursor cursor) { + exercises.clear(); + if (cursor != null && cursor.moveToFirst()) { + do { + int id = cursor.getInt(cursor.getColumnIndexOrThrow(FeedReaderContract.ExerciseEntry.COLUMN_ID)); + String name = cursor.getString(cursor.getColumnIndexOrThrow(FeedReaderContract.ExerciseEntry.COLUMN_NAME)); + int sets = cursor.getInt(cursor.getColumnIndexOrThrow(FeedReaderContract.ExerciseEntry.COLUMN_SETS)); + int reps = cursor.getInt(cursor.getColumnIndexOrThrow(FeedReaderContract.ExerciseEntry.COLUMN_REPS)); + exercises.add(new Exercise(id, name, sets, reps)); + } while (cursor.moveToNext()); + } + notifyDataSetChanged(); + } + + public void removeItem(int position) { + exercises.remove(position); + notifyItemRemoved(position); + } + + class ViewHolder extends RecyclerView.ViewHolder { + TextView textViewName; + TextView textViewSetsReps; + + ViewHolder(View itemView) { + super(itemView); + textViewName = itemView.findViewById(R.id.textViewExerciseName); + textViewSetsReps = itemView.findViewById(R.id.textViewSetsReps); + + itemView.setOnClickListener(v -> { + int position = getAdapterPosition(); + if (listener != null && position != RecyclerView.NO_POSITION) { + listener.onItemClick(exercises.get(position)); + } + }); + } + } +} + diff --git a/app/src/main/java/adapters/WorkoutAdapter.java b/app/src/main/java/adapters/WorkoutAdapter.java new file mode 100644 index 0000000..aa9fbce --- /dev/null +++ b/app/src/main/java/adapters/WorkoutAdapter.java @@ -0,0 +1,88 @@ +package adapters; + +import android.database.Cursor; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.example.gymflow_martim.R; +import models.Workout; +import models.FeedReaderContract; + +import java.util.ArrayList; +import java.util.List; + +public class WorkoutAdapter extends RecyclerView.Adapter { + + private List workouts = new ArrayList<>(); + private OnItemClickListener listener; + + public interface OnItemClickListener { + void onItemClick(Workout workout); + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.listener = listener; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_workout, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + Workout workout = workouts.get(position); + holder.textViewName.setText(workout.getName()); + holder.textViewDate.setText(workout.getDate()); + } + + @Override + public int getItemCount() { + return workouts.size(); + } + + public void setWorkouts(Cursor cursor) { + workouts.clear(); + if (cursor != null && cursor.moveToFirst()) { + do { + int id = cursor.getInt(cursor.getColumnIndexOrThrow(FeedReaderContract.WorkoutEntry.COLUMN_ID)); + String name = cursor.getString(cursor.getColumnIndexOrThrow(FeedReaderContract.WorkoutEntry.COLUMN_NAME)); + String date = cursor.getString(cursor.getColumnIndexOrThrow(FeedReaderContract.WorkoutEntry.COLUMN_DATE)); + workouts.add(new Workout(id, name, date)); + } while (cursor.moveToNext()); + } + notifyDataSetChanged(); + } + + public void removeItem(int position) { + workouts.remove(position); + notifyItemRemoved(position); + } + + class ViewHolder extends RecyclerView.ViewHolder { + TextView textViewName; + TextView textViewDate; + + ViewHolder(View itemView) { + super(itemView); + textViewName = itemView.findViewById(R.id.textViewWorkoutName); + textViewDate = itemView.findViewById(R.id.textViewDate); + + itemView.setOnClickListener(v -> { + int position = getAdapterPosition(); + if (listener != null && position != RecyclerView.NO_POSITION) { + listener.onItemClick(workouts.get(position)); + } + }); + } + } +} + diff --git a/app/src/main/java/com/example/gymflow_martim/MainActivity.java b/app/src/main/java/com/example/gymflow_martim/MainActivity.java new file mode 100644 index 0000000..6ee7faf --- /dev/null +++ b/app/src/main/java/com/example/gymflow_martim/MainActivity.java @@ -0,0 +1,80 @@ +package com.example.gymflow_martim; + +import android.os.Bundle; + +import androidx.activity.EdgeToEdge; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +import com.example.gymflow_martim.fragments.ExercisesFragment; +import com.example.gymflow_martim.fragments.ProgressFragment; +import com.example.gymflow_martim.fragments.SettingsFragment; +import com.example.gymflow_martim.fragments.WorkoutsFragment; +import com.google.android.material.bottomnavigation.BottomNavigationView; + +import com.example.gymflow_martim.R; + +public class MainActivity extends AppCompatActivity { + + private ExercisesFragment exercisesFragment; + private WorkoutsFragment workoutsFragment; + private ProgressFragment progressFragment; + private SettingsFragment settingsFragment; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EdgeToEdge.enable(this); + setContentView(R.layout.activity_main); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + + BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation); + + // Create fragment instances + exercisesFragment = new ExercisesFragment(); + workoutsFragment = new WorkoutsFragment(); + progressFragment = new ProgressFragment(); + settingsFragment = new SettingsFragment(); + + // Load default fragment + loadFragment(exercisesFragment); + + // Set up bottom navigation + bottomNav.setOnItemSelectedListener(item -> { + Fragment selectedFragment = null; + + if (item.getItemId() == R.id.nav_exercises) { + selectedFragment = exercisesFragment; + } else if (item.getItemId() == R.id.nav_workouts) { + selectedFragment = workoutsFragment; + } else if (item.getItemId() == R.id.nav_progress) { + selectedFragment = progressFragment; + } else if (item.getItemId() == R.id.nav_settings) { + selectedFragment = settingsFragment; + } + + if (selectedFragment != null) { + loadFragment(selectedFragment); + return true; + } + + return false; + }); + } + + private void loadFragment(Fragment fragment) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.fragment_container, fragment); + fragmentTransaction.commit(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/gymflow_martim/fragments/ExercisesFragment.java b/app/src/main/java/com/example/gymflow_martim/fragments/ExercisesFragment.java new file mode 100644 index 0000000..17d2df7 --- /dev/null +++ b/app/src/main/java/com/example/gymflow_martim/fragments/ExercisesFragment.java @@ -0,0 +1,92 @@ +package com.example.gymflow_martim.fragments; + +import android.app.AlertDialog; +import android.database.Cursor; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.example.gymflow_martim.R; +import models.Exercise; +import models.db.DbHelper; +import models.FeedReaderContract; +import adapters.ExerciseAdapter; + +public class ExercisesFragment extends Fragment { + + private RecyclerView recyclerView; + private ExerciseAdapter adapter; + private DbHelper dbHelper; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.fragment_exercises, container, false); + + recyclerView = root.findViewById(R.id.recyclerView); + Button buttonAdd = root.findViewById(R.id.buttonAdd); + + dbHelper = DbHelper.getInstance(requireContext()); + + adapter = new ExerciseAdapter(); + adapter.setOnItemClickListener(exercise -> { + // TODO: Show exercise details dialog + }); + + recyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); + recyclerView.setAdapter(adapter); + + buttonAdd.setOnClickListener(v -> showAddExerciseDialog()); + + loadExercises(); + + return root; + } + + private void loadExercises() { + Cursor cursor = dbHelper.getAllExercises(); + adapter.setExercises(cursor); + if (cursor != null) { + cursor.close(); + } + } + + private void showAddExerciseDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); + View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_add_exercise, null); + + EditText editTextName = dialogView.findViewById(R.id.editTextName); + EditText editTextSets = dialogView.findViewById(R.id.editTextSets); + EditText editTextReps = dialogView.findViewById(R.id.editTextReps); + + builder.setView(dialogView) + .setTitle("Adicionar Exercício") + .setPositiveButton("Adicionar", (dialog, which) -> { + String name = editTextName.getText().toString(); + String setsStr = editTextSets.getText().toString(); + String repsStr = editTextReps.getText().toString(); + + if (name.isEmpty() || setsStr.isEmpty() || repsStr.isEmpty()) { + Toast.makeText(requireContext(), "Por favor, preencha todos os campos", Toast.LENGTH_SHORT).show(); + return; + } + + Exercise exercise = new Exercise(name, Integer.parseInt(setsStr), Integer.parseInt(repsStr)); + dbHelper.addExercise(exercise); + loadExercises(); + Toast.makeText(requireContext(), "Exercício adicionado", Toast.LENGTH_SHORT).show(); + }) + .setNegativeButton("Cancelar", null) + .show(); + } +} + diff --git a/app/src/main/java/com/example/gymflow_martim/fragments/ProgressFragment.java b/app/src/main/java/com/example/gymflow_martim/fragments/ProgressFragment.java new file mode 100644 index 0000000..4515468 --- /dev/null +++ b/app/src/main/java/com/example/gymflow_martim/fragments/ProgressFragment.java @@ -0,0 +1,94 @@ +package com.example.gymflow_martim.fragments; + +import android.app.AlertDialog; +import android.database.Cursor; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.example.gymflow_martim.R; +import models.ProgressEntry; +import models.db.DbHelper; +import models.FeedReaderContract; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class ProgressFragment extends Fragment { + + private TextView textViewCurrentDate; + private TextView textViewValue; + private DbHelper dbHelper; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.fragment_progress, container, false); + + textViewCurrentDate = root.findViewById(R.id.textViewCurrentDate); + textViewValue = root.findViewById(R.id.textViewValue); + Button buttonAdd = root.findViewById(R.id.buttonAdd); + + dbHelper = DbHelper.getInstance(requireContext()); + + buttonAdd.setOnClickListener(v -> showAddProgressDialog()); + + loadLatestProgress(); + + return root; + } + + private void loadLatestProgress() { + Cursor cursor = dbHelper.getAllProgressEntries("Peso corporal"); + + if (cursor != null && cursor.moveToLast()) { + String date = cursor.getString(cursor.getColumnIndexOrThrow(FeedReaderContract.ProgressEntry.COLUMN_DATE)); + double value = cursor.getDouble(cursor.getColumnIndexOrThrow(FeedReaderContract.ProgressEntry.COLUMN_VALUE)); + + textViewCurrentDate.setText(date); + textViewValue.setText(String.format(Locale.getDefault(), "%.1f kg", value)); + } + + if (cursor != null) { + cursor.close(); + } + } + + private void showAddProgressDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); + View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_add_progress, null); + + EditText editTextValue = dialogView.findViewById(R.id.editTextValue); + + builder.setView(dialogView) + .setTitle("Adicionar Registo") + .setPositiveButton("Adicionar", (dialog, which) -> { + String valueStr = editTextValue.getText().toString(); + + if (valueStr.isEmpty()) { + Toast.makeText(requireContext(), "Por favor, insira o valor", Toast.LENGTH_SHORT).show(); + return; + } + + SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()); + String date = sdf.format(new Date()); + + ProgressEntry entry = new ProgressEntry(date, "Peso corporal", Double.parseDouble(valueStr)); + dbHelper.addProgressEntry(entry); + loadLatestProgress(); + Toast.makeText(requireContext(), "Registo adicionado", Toast.LENGTH_SHORT).show(); + }) + .setNegativeButton("Cancelar", null) + .show(); + } +} + diff --git a/app/src/main/java/com/example/gymflow_martim/fragments/SettingsFragment.java b/app/src/main/java/com/example/gymflow_martim/fragments/SettingsFragment.java new file mode 100644 index 0000000..bef4c55 --- /dev/null +++ b/app/src/main/java/com/example/gymflow_martim/fragments/SettingsFragment.java @@ -0,0 +1,114 @@ +package com.example.gymflow_martim.fragments; + +import android.database.Cursor; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.Spinner; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.example.gymflow_martim.R; +import models.User; +import models.db.DbHelper; +import models.FeedReaderContract; + +import android.widget.ArrayAdapter; + +public class SettingsFragment extends Fragment { + + private EditText editTextName; + private EditText editTextAge; + private EditText editTextHeight; + private EditText editTextWeight; + private Spinner spinnerGender; + private RadioGroup radioGroupTheme; + private RadioButton radioLight; + private DbHelper dbHelper; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.fragment_settings, container, false); + + editTextName = root.findViewById(R.id.editTextName); + editTextAge = root.findViewById(R.id.editTextAge); + editTextHeight = root.findViewById(R.id.editTextHeight); + editTextWeight = root.findViewById(R.id.editTextWeight); + spinnerGender = root.findViewById(R.id.spinnerGender); + radioGroupTheme = root.findViewById(R.id.radioGroupTheme); + radioLight = root.findViewById(R.id.radioLight); + + Button buttonSave = root.findViewById(R.id.buttonSave); + + dbHelper = DbHelper.getInstance(requireContext()); + + String[] genders = {"Masculino", "Feminino"}; + ArrayAdapter adapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, genders); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinnerGender.setAdapter(adapter); + + buttonSave.setOnClickListener(v -> saveSettings()); + + loadSettings(); + + return root; + } + + private void loadSettings() { + if (dbHelper.userExists()) { + Cursor cursor = dbHelper.getUser(); + if (cursor != null && cursor.moveToFirst()) { + editTextName.setText(cursor.getString(cursor.getColumnIndexOrThrow(FeedReaderContract.UserEntry.COLUMN_NAME))); + editTextAge.setText(String.valueOf(cursor.getInt(cursor.getColumnIndexOrThrow(FeedReaderContract.UserEntry.COLUMN_AGE)))); + editTextHeight.setText(String.valueOf(cursor.getDouble(cursor.getColumnIndexOrThrow(FeedReaderContract.UserEntry.COLUMN_HEIGHT)))); + editTextWeight.setText(String.valueOf(cursor.getDouble(cursor.getColumnIndexOrThrow(FeedReaderContract.UserEntry.COLUMN_WEIGHT)))); + String gender = cursor.getString(cursor.getColumnIndexOrThrow(FeedReaderContract.UserEntry.COLUMN_GENDER)); + int position = gender.equals("Masculino") ? 0 : 1; + spinnerGender.setSelection(position); + String theme = cursor.getString(cursor.getColumnIndexOrThrow(FeedReaderContract.UserEntry.COLUMN_THEME)); + if ("Escuro".equals(theme)) { + radioGroupTheme.check(R.id.radioDark); + } + } + if (cursor != null) { + cursor.close(); + } + } + } + + private void saveSettings() { + String name = editTextName.getText().toString(); + String ageStr = editTextAge.getText().toString(); + String heightStr = editTextHeight.getText().toString(); + String weightStr = editTextWeight.getText().toString(); + String gender = spinnerGender.getSelectedItem().toString(); + + RadioButton selectedRadio = getView().findViewById(radioGroupTheme.getCheckedRadioButtonId()); + String theme = selectedRadio.getText().toString(); + + if (name.isEmpty() || ageStr.isEmpty() || heightStr.isEmpty() || weightStr.isEmpty()) { + Toast.makeText(requireContext(), "Por favor, preencha todos os campos", Toast.LENGTH_SHORT).show(); + return; + } + + User user = new User(name, Integer.parseInt(ageStr), Double.parseDouble(heightStr), + Double.parseDouble(weightStr), gender, theme); + + if (dbHelper.userExists()) { + dbHelper.updateUser(user); + Toast.makeText(requireContext(), "Dados atualizados", Toast.LENGTH_SHORT).show(); + } else { + dbHelper.saveUser(user); + Toast.makeText(requireContext(), "Dados guardados", Toast.LENGTH_SHORT).show(); + } + } +} + diff --git a/app/src/main/java/com/example/gymflow_martim/fragments/WorkoutsFragment.java b/app/src/main/java/com/example/gymflow_martim/fragments/WorkoutsFragment.java new file mode 100644 index 0000000..cbeb972 --- /dev/null +++ b/app/src/main/java/com/example/gymflow_martim/fragments/WorkoutsFragment.java @@ -0,0 +1,94 @@ +package com.example.gymflow_martim.fragments; + +import android.app.AlertDialog; +import android.database.Cursor; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.example.gymflow_martim.R; +import models.Workout; +import models.db.DbHelper; +import adapters.WorkoutAdapter; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class WorkoutsFragment extends Fragment { + + private RecyclerView recyclerView; + private WorkoutAdapter adapter; + private DbHelper dbHelper; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.fragment_workouts, container, false); + + recyclerView = root.findViewById(R.id.recyclerView); + Button buttonCreate = root.findViewById(R.id.buttonCreate); + + dbHelper = DbHelper.getInstance(requireContext()); + + adapter = new WorkoutAdapter(); + adapter.setOnItemClickListener(workout -> { + // TODO: Show workout details dialog + }); + + recyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); + recyclerView.setAdapter(adapter); + + buttonCreate.setOnClickListener(v -> showCreateWorkoutDialog()); + + loadWorkouts(); + + return root; + } + + private void loadWorkouts() { + Cursor cursor = dbHelper.getAllWorkouts(); + adapter.setWorkouts(cursor); + if (cursor != null) { + cursor.close(); + } + } + + private void showCreateWorkoutDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); + View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_add_workout, null); + + EditText editTextName = dialogView.findViewById(R.id.editTextName); + + builder.setView(dialogView) + .setTitle("Criar Novo Treino") + .setPositiveButton("Criar", (dialog, which) -> { + String name = editTextName.getText().toString(); + + if (name.isEmpty()) { + Toast.makeText(requireContext(), "Por favor, insira o nome do treino", Toast.LENGTH_SHORT).show(); + return; + } + + SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy", Locale.getDefault()); + String date = sdf.format(new Date()); + + Workout workout = new Workout(name, date); + dbHelper.addWorkout(workout); + loadWorkouts(); + Toast.makeText(requireContext(), "Treino criado", Toast.LENGTH_SHORT).show(); + }) + .setNegativeButton("Cancelar", null) + .show(); + } +} + diff --git a/app/src/main/java/models/Exercise.java b/app/src/main/java/models/Exercise.java new file mode 100644 index 0000000..7b088bd --- /dev/null +++ b/app/src/main/java/models/Exercise.java @@ -0,0 +1,62 @@ +package models; + +public class Exercise { + private int id; + private String name; + private int sets; + private int reps; + + public Exercise() { + } + + public Exercise(String name, int sets, int reps) { + this.name = name; + this.sets = sets; + this.reps = reps; + } + + public Exercise(int id, String name, int sets, int reps) { + this.id = id; + this.name = name; + this.sets = sets; + this.reps = reps; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getSets() { + return sets; + } + + public void setSets(int sets) { + this.sets = sets; + } + + public int getReps() { + return reps; + } + + public void setReps(int reps) { + this.reps = reps; + } + + @Override + public String toString() { + return sets + " x " + reps; + } +} + diff --git a/app/src/main/java/models/FeedReaderContract.java b/app/src/main/java/models/FeedReaderContract.java new file mode 100644 index 0000000..ce2cddd --- /dev/null +++ b/app/src/main/java/models/FeedReaderContract.java @@ -0,0 +1,48 @@ +package models; + +public class FeedReaderContract { + + public static class ExerciseEntry { + public static final String TABLE_NAME = "exercises"; + public static final String COLUMN_ID = "id"; + public static final String COLUMN_NAME = "name"; + public static final String COLUMN_SETS = "sets"; + public static final String COLUMN_REPS = "reps"; + } + + public static class WorkoutEntry { + public static final String TABLE_NAME = "workouts"; + public static final String COLUMN_ID = "id"; + public static final String COLUMN_NAME = "name"; + public static final String COLUMN_DATE = "date"; + } + + public static class WorkoutExerciseEntry { + public static final String TABLE_NAME = "workout_exercises"; + public static final String COLUMN_ID = "id"; + public static final String COLUMN_WORKOUT_ID = "workout_id"; + public static final String COLUMN_EXERCISE_NAME = "exercise_name"; + public static final String COLUMN_SETS = "sets"; + public static final String COLUMN_REPS = "reps"; + } + + public static class ProgressEntry { + public static final String TABLE_NAME = "progress"; + public static final String COLUMN_ID = "id"; + public static final String COLUMN_DATE = "date"; + public static final String COLUMN_METRIC = "metric"; + public static final String COLUMN_VALUE = "value"; + } + + public static class UserEntry { + public static final String TABLE_NAME = "user"; + public static final String COLUMN_ID = "id"; + public static final String COLUMN_NAME = "name"; + public static final String COLUMN_AGE = "age"; + public static final String COLUMN_HEIGHT = "height"; + public static final String COLUMN_WEIGHT = "weight"; + public static final String COLUMN_GENDER = "gender"; + public static final String COLUMN_THEME = "theme"; + } +} + diff --git a/app/src/main/java/models/ProgressEntry.java b/app/src/main/java/models/ProgressEntry.java new file mode 100644 index 0000000..001b604 --- /dev/null +++ b/app/src/main/java/models/ProgressEntry.java @@ -0,0 +1,57 @@ +package models; + +public class ProgressEntry { + private int id; + private String date; + private String metric; + private double value; + + public ProgressEntry() { + } + + public ProgressEntry(String date, String metric, double value) { + this.date = date; + this.metric = metric; + this.value = value; + } + + public ProgressEntry(int id, String date, String metric, double value) { + this.id = id; + this.date = date; + this.metric = metric; + this.value = value; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getMetric() { + return metric; + } + + public void setMetric(String metric) { + this.metric = metric; + } + + public double getValue() { + return value; + } + + public void setValue(double value) { + this.value = value; + } +} + diff --git a/app/src/main/java/models/User.java b/app/src/main/java/models/User.java new file mode 100644 index 0000000..60640a4 --- /dev/null +++ b/app/src/main/java/models/User.java @@ -0,0 +1,80 @@ +package models; + +public class User { + private int id; + private String name; + private int age; + private double height; + private double weight; + private String gender; + private String theme; + + public User() { + } + + public User(String name, int age, double height, double weight, String gender, String theme) { + this.name = name; + this.age = age; + this.height = height; + this.weight = weight; + this.gender = gender; + this.theme = theme; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public double getHeight() { + return height; + } + + public void setHeight(double height) { + this.height = height; + } + + public double getWeight() { + return weight; + } + + public void setWeight(double weight) { + this.weight = weight; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getTheme() { + return theme; + } + + public void setTheme(String theme) { + this.theme = theme; + } +} + diff --git a/app/src/main/java/models/Workout.java b/app/src/main/java/models/Workout.java new file mode 100644 index 0000000..0324560 --- /dev/null +++ b/app/src/main/java/models/Workout.java @@ -0,0 +1,57 @@ +package models; + +import java.util.List; + +public class Workout { + private int id; + private String name; + private String date; + private List exercises; + + public Workout() { + } + + public Workout(String name, String date) { + this.name = name; + this.date = date; + } + + public Workout(int id, String name, String date) { + this.id = id; + this.name = name; + this.date = date; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public List getExercises() { + return exercises; + } + + public void setExercises(List exercises) { + this.exercises = exercises; + } +} + diff --git a/app/src/main/java/models/db/DbHelper.java b/app/src/main/java/models/db/DbHelper.java new file mode 100644 index 0000000..0dd16d6 --- /dev/null +++ b/app/src/main/java/models/db/DbHelper.java @@ -0,0 +1,199 @@ +package models.db; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import models.Exercise; +import models.ProgressEntry; +import models.User; +import models.Workout; +import models.FeedReaderContract; + +public class DbHelper extends SQLiteOpenHelper { + + private static final String DATABASE_NAME = "GymFlow.db"; + private static final int DATABASE_VERSION = 1; + private static DbHelper instance; + + private DbHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + public static synchronized DbHelper getInstance(Context context) { + if (instance == null) { + instance = new DbHelper(context.getApplicationContext()); + } + return instance; + } + + @Override + public void onCreate(SQLiteDatabase db) { + // Create exercises table + String SQL_CREATE_EXERCISES_TABLE = "CREATE TABLE " + + FeedReaderContract.ExerciseEntry.TABLE_NAME + " (" + + FeedReaderContract.ExerciseEntry.COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + FeedReaderContract.ExerciseEntry.COLUMN_NAME + " TEXT NOT NULL, " + + FeedReaderContract.ExerciseEntry.COLUMN_SETS + " INTEGER NOT NULL, " + + FeedReaderContract.ExerciseEntry.COLUMN_REPS + " INTEGER NOT NULL);"; + + // Create workouts table + String SQL_CREATE_WORKOUTS_TABLE = "CREATE TABLE " + + FeedReaderContract.WorkoutEntry.TABLE_NAME + " (" + + FeedReaderContract.WorkoutEntry.COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + FeedReaderContract.WorkoutEntry.COLUMN_NAME + " TEXT NOT NULL, " + + FeedReaderContract.WorkoutEntry.COLUMN_DATE + " TEXT NOT NULL);"; + + // Create workout_exercises table + String SQL_CREATE_WORKOUT_EXERCISES_TABLE = "CREATE TABLE " + + FeedReaderContract.WorkoutExerciseEntry.TABLE_NAME + " (" + + FeedReaderContract.WorkoutExerciseEntry.COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + FeedReaderContract.WorkoutExerciseEntry.COLUMN_WORKOUT_ID + " INTEGER NOT NULL, " + + FeedReaderContract.WorkoutExerciseEntry.COLUMN_EXERCISE_NAME + " TEXT NOT NULL, " + + FeedReaderContract.WorkoutExerciseEntry.COLUMN_SETS + " INTEGER NOT NULL, " + + FeedReaderContract.WorkoutExerciseEntry.COLUMN_REPS + " INTEGER NOT NULL);"; + + // Create progress table + String SQL_CREATE_PROGRESS_TABLE = "CREATE TABLE " + + FeedReaderContract.ProgressEntry.TABLE_NAME + " (" + + FeedReaderContract.ProgressEntry.COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + FeedReaderContract.ProgressEntry.COLUMN_DATE + " TEXT NOT NULL, " + + FeedReaderContract.ProgressEntry.COLUMN_METRIC + " TEXT NOT NULL, " + + FeedReaderContract.ProgressEntry.COLUMN_VALUE + " REAL NOT NULL);"; + + // Create user table + String SQL_CREATE_USER_TABLE = "CREATE TABLE " + + FeedReaderContract.UserEntry.TABLE_NAME + " (" + + FeedReaderContract.UserEntry.COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + FeedReaderContract.UserEntry.COLUMN_NAME + " TEXT, " + + FeedReaderContract.UserEntry.COLUMN_AGE + " INTEGER, " + + FeedReaderContract.UserEntry.COLUMN_HEIGHT + " REAL, " + + FeedReaderContract.UserEntry.COLUMN_WEIGHT + " REAL, " + + FeedReaderContract.UserEntry.COLUMN_GENDER + " TEXT, " + + FeedReaderContract.UserEntry.COLUMN_THEME + " TEXT);"; + + db.execSQL(SQL_CREATE_EXERCISES_TABLE); + db.execSQL(SQL_CREATE_WORKOUTS_TABLE); + db.execSQL(SQL_CREATE_WORKOUT_EXERCISES_TABLE); + db.execSQL(SQL_CREATE_PROGRESS_TABLE); + db.execSQL(SQL_CREATE_USER_TABLE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE IF EXISTS " + FeedReaderContract.ExerciseEntry.TABLE_NAME); + db.execSQL("DROP TABLE IF EXISTS " + FeedReaderContract.WorkoutEntry.TABLE_NAME); + db.execSQL("DROP TABLE IF EXISTS " + FeedReaderContract.WorkoutExerciseEntry.TABLE_NAME); + db.execSQL("DROP TABLE IF EXISTS " + FeedReaderContract.ProgressEntry.TABLE_NAME); + db.execSQL("DROP TABLE IF EXISTS " + FeedReaderContract.UserEntry.TABLE_NAME); + onCreate(db); + } + + // Exercise methods + public long addExercise(Exercise exercise) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(FeedReaderContract.ExerciseEntry.COLUMN_NAME, exercise.getName()); + values.put(FeedReaderContract.ExerciseEntry.COLUMN_SETS, exercise.getSets()); + values.put(FeedReaderContract.ExerciseEntry.COLUMN_REPS, exercise.getReps()); + return db.insert(FeedReaderContract.ExerciseEntry.TABLE_NAME, null, values); + } + + public Cursor getAllExercises() { + SQLiteDatabase db = this.getReadableDatabase(); + return db.query(FeedReaderContract.ExerciseEntry.TABLE_NAME, + null, null, null, null, null, FeedReaderContract.ExerciseEntry.COLUMN_NAME); + } + + public boolean deleteExercise(int id) { + SQLiteDatabase db = this.getWritableDatabase(); + return db.delete(FeedReaderContract.ExerciseEntry.TABLE_NAME, + FeedReaderContract.ExerciseEntry.COLUMN_ID + "=?", new String[]{String.valueOf(id)}) > 0; + } + + // Workout methods + public long addWorkout(Workout workout) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(FeedReaderContract.WorkoutEntry.COLUMN_NAME, workout.getName()); + values.put(FeedReaderContract.WorkoutEntry.COLUMN_DATE, workout.getDate()); + return db.insert(FeedReaderContract.WorkoutEntry.TABLE_NAME, null, values); + } + + public Cursor getAllWorkouts() { + SQLiteDatabase db = this.getReadableDatabase(); + return db.query(FeedReaderContract.WorkoutEntry.TABLE_NAME, + null, null, null, null, null, FeedReaderContract.WorkoutEntry.COLUMN_DATE + " DESC"); + } + + public boolean deleteWorkout(int id) { + SQLiteDatabase db = this.getWritableDatabase(); + db.delete(FeedReaderContract.WorkoutExerciseEntry.TABLE_NAME, + FeedReaderContract.WorkoutExerciseEntry.COLUMN_WORKOUT_ID + "=?", new String[]{String.valueOf(id)}); + return db.delete(FeedReaderContract.WorkoutEntry.TABLE_NAME, + FeedReaderContract.WorkoutEntry.COLUMN_ID + "=?", new String[]{String.valueOf(id)}) > 0; + } + + // Progress methods + public long addProgressEntry(ProgressEntry entry) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(FeedReaderContract.ProgressEntry.COLUMN_DATE, entry.getDate()); + values.put(FeedReaderContract.ProgressEntry.COLUMN_METRIC, entry.getMetric()); + values.put(FeedReaderContract.ProgressEntry.COLUMN_VALUE, entry.getValue()); + return db.insert(FeedReaderContract.ProgressEntry.TABLE_NAME, null, values); + } + + public Cursor getAllProgressEntries(String metric) { + SQLiteDatabase db = this.getReadableDatabase(); + String selection = FeedReaderContract.ProgressEntry.COLUMN_METRIC + "=?"; + String[] selectionArgs = {metric}; + return db.query(FeedReaderContract.ProgressEntry.TABLE_NAME, + null, selection, selectionArgs, null, null, FeedReaderContract.ProgressEntry.COLUMN_DATE + " ASC"); + } + + // User methods + public long saveUser(User user) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(FeedReaderContract.UserEntry.COLUMN_NAME, user.getName()); + values.put(FeedReaderContract.UserEntry.COLUMN_AGE, user.getAge()); + values.put(FeedReaderContract.UserEntry.COLUMN_HEIGHT, user.getHeight()); + values.put(FeedReaderContract.UserEntry.COLUMN_WEIGHT, user.getWeight()); + values.put(FeedReaderContract.UserEntry.COLUMN_GENDER, user.getGender()); + values.put(FeedReaderContract.UserEntry.COLUMN_THEME, user.getTheme()); + return db.insert(FeedReaderContract.UserEntry.TABLE_NAME, null, values); + } + + public void updateUser(User user) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(FeedReaderContract.UserEntry.COLUMN_NAME, user.getName()); + values.put(FeedReaderContract.UserEntry.COLUMN_AGE, user.getAge()); + values.put(FeedReaderContract.UserEntry.COLUMN_HEIGHT, user.getHeight()); + values.put(FeedReaderContract.UserEntry.COLUMN_WEIGHT, user.getWeight()); + values.put(FeedReaderContract.UserEntry.COLUMN_GENDER, user.getGender()); + values.put(FeedReaderContract.UserEntry.COLUMN_THEME, user.getTheme()); + db.update(FeedReaderContract.UserEntry.TABLE_NAME, values, + FeedReaderContract.UserEntry.COLUMN_ID + "=1", null); + } + + public Cursor getUser() { + SQLiteDatabase db = this.getReadableDatabase(); + return db.query(FeedReaderContract.UserEntry.TABLE_NAME, + null, null, null, null, null, null, "1"); + } + + public boolean userExists() { + SQLiteDatabase db = this.getReadableDatabase(); + Cursor cursor = db.query(FeedReaderContract.UserEntry.TABLE_NAME, + new String[]{FeedReaderContract.UserEntry.COLUMN_ID}, + null, null, null, null, null, "1"); + boolean exists = cursor.getCount() > 0; + cursor.close(); + return exists; + } +} + diff --git a/app/src/main/res/drawable/bg_card_exercise.xml b/app/src/main/res/drawable/bg_card_exercise.xml new file mode 100644 index 0000000..3b8ebd1 --- /dev/null +++ b/app/src/main/res/drawable/bg_card_exercise.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/bg_card_workout.xml b/app/src/main/res/drawable/bg_card_workout.xml new file mode 100644 index 0000000..99efdf6 --- /dev/null +++ b/app/src/main/res/drawable/bg_card_workout.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/bg_pattern.xml b/app/src/main/res/drawable/bg_pattern.xml new file mode 100644 index 0000000..33df9d5 --- /dev/null +++ b/app/src/main/res/drawable/bg_pattern.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/drawable/empty_state_exercises.xml b/app/src/main/res/drawable/empty_state_exercises.xml new file mode 100644 index 0000000..b0cb9b7 --- /dev/null +++ b/app/src/main/res/drawable/empty_state_exercises.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/empty_state_progress.xml b/app/src/main/res/drawable/empty_state_progress.xml new file mode 100644 index 0000000..4d6ee32 --- /dev/null +++ b/app/src/main/res/drawable/empty_state_progress.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/empty_state_workouts.xml b/app/src/main/res/drawable/empty_state_workouts.xml new file mode 100644 index 0000000..39f5dc9 --- /dev/null +++ b/app/src/main/res/drawable/empty_state_workouts.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_calendar.xml b/app/src/main/res/drawable/ic_calendar.xml new file mode 100644 index 0000000..2278116 --- /dev/null +++ b/app/src/main/res/drawable/ic_calendar.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_dumbbell.xml b/app/src/main/res/drawable/ic_dumbbell.xml new file mode 100644 index 0000000..f648f59 --- /dev/null +++ b/app/src/main/res/drawable/ic_dumbbell.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_graph.xml b/app/src/main/res/drawable/ic_graph.xml new file mode 100644 index 0000000..a702126 --- /dev/null +++ b/app/src/main/res/drawable/ic_graph.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_app_logo.xml b/app/src/main/res/drawable/ic_launcher_app_logo.xml new file mode 100644 index 0000000..acbd7ad --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_app_logo.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..844943b --- /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..c834e07 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml new file mode 100644 index 0000000..56dfdd5 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/nav_item_color.xml b/app/src/main/res/drawable/nav_item_color.xml new file mode 100644 index 0000000..c0c1dc4 --- /dev/null +++ b/app/src/main/res/drawable/nav_item_color.xml @@ -0,0 +1,8 @@ + + + + + + + + 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..9077841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_add_exercise.xml b/app/src/main/res/layout/dialog_add_exercise.xml new file mode 100644 index 0000000..53e14f6 --- /dev/null +++ b/app/src/main/res/layout/dialog_add_exercise.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_add_progress.xml b/app/src/main/res/layout/dialog_add_progress.xml new file mode 100644 index 0000000..85fda2f --- /dev/null +++ b/app/src/main/res/layout/dialog_add_progress.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_add_workout.xml b/app/src/main/res/layout/dialog_add_workout.xml new file mode 100644 index 0000000..ac3fd24 --- /dev/null +++ b/app/src/main/res/layout/dialog_add_workout.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_exercises.xml b/app/src/main/res/layout/fragment_exercises.xml new file mode 100644 index 0000000..c41e679 --- /dev/null +++ b/app/src/main/res/layout/fragment_exercises.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_progress.xml b/app/src/main/res/layout/fragment_progress.xml new file mode 100644 index 0000000..ab99112 --- /dev/null +++ b/app/src/main/res/layout/fragment_progress.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml new file mode 100644 index 0000000..33f0c23 --- /dev/null +++ b/app/src/main/res/layout/fragment_settings.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_workouts.xml b/app/src/main/res/layout/fragment_workouts.xml new file mode 100644 index 0000000..8fa6912 --- /dev/null +++ b/app/src/main/res/layout/fragment_workouts.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_exercise.xml b/app/src/main/res/layout/item_exercise.xml new file mode 100644 index 0000000..34fc722 --- /dev/null +++ b/app/src/main/res/layout/item_exercise.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_workout.xml b/app/src/main/res/layout/item_workout.xml new file mode 100644 index 0000000..867a077 --- /dev/null +++ b/app/src/main/res/layout/item_workout.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml new file mode 100644 index 0000000..863e954 --- /dev/null +++ b/app/src/main/res/menu/bottom_nav_menu.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/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/colors.xml b/app/src/main/res/values-night/colors.xml new file mode 100644 index 0000000..644bc34 --- /dev/null +++ b/app/src/main/res/values-night/colors.xml @@ -0,0 +1,16 @@ + + + #90CAF9 + #002F6C + #003C8F + #D1E3FF + + #121212 + #E3E3E3 + #2C2C2C + #C6C6C6 + + #8C88FF + #121212 + + 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..5009b20 --- /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..c8a4266 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,22 @@ + + + #FF000000 + #FFFFFFFF + + #1565C0 + #FFFFFF + #D1E3FF + #001D36 + + #FFFBFE + #1C1B1F + #E7E0EC + #49454F + + #5E5ADB + #FFFFFF + + + #2196F3 + #1976D2 + \ 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..4e66f32 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,42 @@ + + GymFlow-Martim + + + Exercícios + Treinos + Progresso + Definições + + + Adicionar Exercício + Nome do exercício + Séries + Repetições + + + Criar Novo Treino + Nome do treino + + + Adicionar Registo + Peso corporal + + + Nome + Idade + Altura (cm) + Peso (kg) + Género + Tema da aplicação + Claro + Escuro + Guardar + + João + 29 + 180 + 82.0 + + Masculino + Feminino + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..4f4bde6 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..375929b --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,31 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 0000000..4df9255 --- /dev/null +++ b/app/src/main/res/xml/backup_rules.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 0000000..9ee9997 --- /dev/null +++ b/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/test/java/com/example/gymflow_martim/ExampleUnitTest.java b/app/src/test/java/com/example/gymflow_martim/ExampleUnitTest.java new file mode 100644 index 0000000..f090a45 --- /dev/null +++ b/app/src/test/java/com/example/gymflow_martim/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.example.gymflow_martim; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..3756278 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,4 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + alias(libs.plugins.android.application) apply false +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..4387edc --- /dev/null +++ b/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. For more details, visit +# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..f6619f4 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,28 @@ +[versions] +agp = "8.13.0" +junit = "4.13.2" +junitVersion = "1.1.5" +espressoCore = "3.5.1" +appcompat = "1.7.1" +material = "1.10.0" +activity = "1.11.0" +constraintlayout = "2.1.4" +recyclerview = "1.3.2" +cardview = "1.0.0" +coordinatorlayout = "1.2.0" + +[libraries] +junit = { group = "junit", name = "junit", version.ref = "junit" } +ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } +activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } +constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } +recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" } +cardview = { group = "androidx.cardview", name = "cardview", version.ref = "cardview" } +coordinatorlayout = { group = "androidx.coordinatorlayout", name = "coordinatorlayout", version.ref = "coordinatorlayout" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..12c37ed --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Oct 23 15:45:18 WEST 2025 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..ac1b06f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..fef4265 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,24 @@ +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "GymFlow-Martim" +include(":app") + \ No newline at end of file