forked from stud179277/Timer
		
	добавление данных тренировок и упражнений
This commit is contained in:
		
							parent
							
								
									505f533f04
								
							
						
					
					
						commit
						3078443367
					
				| @ -0,0 +1,67 @@ | ||||
| { | ||||
|   "formatVersion": 1, | ||||
|   "database": { | ||||
|     "version": 1, | ||||
|     "identityHash": "6ba5dfef7859cedba19af71b404c9e4f", | ||||
|     "entities": [ | ||||
|       { | ||||
|         "tableName": "workouts", | ||||
|         "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `numApproaches` INTEGER NOT NULL, `numExercises` INTEGER NOT NULL, `restBetweenExercises` INTEGER NOT NULL, `restBetweenApproaches` INTEGER NOT NULL, `exerciseDuration` INTEGER NOT NULL)", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "id", | ||||
|             "columnName": "id", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "name", | ||||
|             "columnName": "name", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "numApproaches", | ||||
|             "columnName": "numApproaches", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "numExercises", | ||||
|             "columnName": "numExercises", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "restBetweenExercises", | ||||
|             "columnName": "restBetweenExercises", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "restBetweenApproaches", | ||||
|             "columnName": "restBetweenApproaches", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "exerciseDuration", | ||||
|             "columnName": "exerciseDuration", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "autoGenerate": true, | ||||
|           "columnNames": [ | ||||
|             "id" | ||||
|           ] | ||||
|         } | ||||
|       } | ||||
|     ], | ||||
|     "setupQueries": [ | ||||
|       "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", | ||||
|       "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6ba5dfef7859cedba19af71b404c9e4f')" | ||||
|     ] | ||||
|   } | ||||
| } | ||||
| @ -1,9 +0,0 @@ | ||||
| package com.example.timert | ||||
| import androidx.room.Database | ||||
| import androidx.room.RoomDatabase | ||||
| import com.example.timert.Workout | ||||
| import com.example.timert.WorkoutDao | ||||
| @Database(entities = [Workout::class], version = 1) | ||||
| abstract class AppDatabase : RoomDatabase() { | ||||
|     abstract fun workoutDao(): WorkoutDao | ||||
| } | ||||
| @ -1,27 +0,0 @@ | ||||
| package com.example.timert | ||||
| 
 | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.TextView | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| 
 | ||||
| class WorkoutAdapter(private val workouts: List<Workout>) : RecyclerView.Adapter<WorkoutAdapter.WorkoutViewHolder>() { | ||||
| 
 | ||||
|     class WorkoutViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { | ||||
|         val textViewName: TextView = itemView.findViewById(R.id.textViewName) | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WorkoutViewHolder { | ||||
|         val itemView = LayoutInflater.from(parent.context) | ||||
|             .inflate(R.layout.workout_item, parent, false) | ||||
|         return WorkoutViewHolder(itemView) | ||||
|     } | ||||
| 
 | ||||
|     override fun onBindViewHolder(holder: WorkoutViewHolder, position: Int) { | ||||
|         val currentItem = workouts[position] | ||||
|         holder.textViewName.text = currentItem.name | ||||
|     } | ||||
| 
 | ||||
|     override fun getItemCount() = workouts.size | ||||
| } | ||||
| @ -6,13 +6,24 @@ import android.os.Bundle | ||||
| import android.widget.Button | ||||
| import android.widget.EditText | ||||
| import android.widget.ImageView | ||||
| import android.widget.Toast | ||||
| import androidx.activity.enableEdgeToEdge | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.core.view.ViewCompat | ||||
| import androidx.core.view.WindowInsetsCompat | ||||
| import androidx.lifecycle.ViewModelProvider | ||||
| import com.example.timert.com.example.timert.data.entity.Workout | ||||
| import com.example.timert.data.viewModel.WorkoutViewModel | ||||
| 
 | ||||
| 
 | ||||
| class AddWorkout : AppCompatActivity() { | ||||
|     private var isSave = false | ||||
|     private lateinit var editWorkoutView: EditText | ||||
|     private lateinit var numWorkoutView: EditText | ||||
|     private lateinit var numRestWorkoutView: EditText | ||||
|     private lateinit var numRestSetsView: EditText | ||||
|     private lateinit var numSetsView: EditText | ||||
|     private lateinit var timeWorkoutView: EditText | ||||
| 
 | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
| @ -23,11 +34,62 @@ class AddWorkout : AppCompatActivity() { | ||||
|             v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) | ||||
|             insets | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         val workoutViewModel = ViewModelProvider( | ||||
|             this, | ||||
|             ViewModelProvider.AndroidViewModelFactory.getInstance(application) | ||||
|         )[WorkoutViewModel::class.java] | ||||
| 
 | ||||
|         editWorkoutView = findViewById(R.id.name_training) | ||||
|         numWorkoutView = findViewById(R.id.num_exercise) | ||||
|         numRestWorkoutView = findViewById(R.id.rest_workout_all) | ||||
|         numRestSetsView = findViewById(R.id.rest_sets_all) | ||||
|         numSetsView = findViewById(R.id.numbers_of_sets_all) | ||||
|         timeWorkoutView = findViewById(R.id.time_work_all) | ||||
| 
 | ||||
| 
 | ||||
|         val buttonSaveAll: Button = findViewById(R.id.btn_save_all) | ||||
|         buttonSaveAll.setOnClickListener { | ||||
|             val intent = Intent(this, MainActivity::class.java) | ||||
|             startActivity(intent) | ||||
|             isSave = true | ||||
| 
 | ||||
|             val workoutName = editWorkoutView.text.toString() | ||||
|             val numWorkoutText = numWorkoutView.text.toString() | ||||
|             val restWorkoutText = numRestWorkoutView.text.toString() | ||||
|             val restSetsText = numRestSetsView.text.toString() | ||||
|             val numSetsText = numSetsView.text.toString() | ||||
|             val timeWorkText =  timeWorkoutView.text.toString() | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|             if (workoutName.isBlank() || numSetsText.isBlank() || restSetsText.isBlank()||numWorkoutText.isBlank() || restWorkoutText.isBlank() || timeWorkText.isBlank()) { | ||||
|                 Toast.makeText(this, "Заполните все поля", Toast.LENGTH_SHORT).show() | ||||
|             } else { | ||||
|                 val numExercise = numWorkoutText.toIntOrNull() | ||||
|                 val restExercise = restWorkoutText.toIntOrNull() | ||||
|                 val numSets = numSetsText.toIntOrNull() | ||||
|                 val restSets = restSetsText.toIntOrNull() | ||||
|                 val timeWorkExercise = timeWorkText.toIntOrNull() | ||||
| 
 | ||||
|                 if (numSets == null || restSets == null || numExercise == null || restExercise == null || timeWorkExercise == null) { | ||||
|                     Toast.makeText(this, "Неверный формат чисел", Toast.LENGTH_SHORT).show() | ||||
|                     return@setOnClickListener | ||||
|                 } | ||||
| 
 | ||||
|                 val newWorkout = Workout( | ||||
|                     name = workoutName, | ||||
|                     numApproaches = numSets, | ||||
|                     numExercises = numExercise, | ||||
|                     restBetweenExercises = restExercise, | ||||
|                     restBetweenApproaches = restSets, | ||||
|                     exerciseDuration = timeWorkExercise, | ||||
|                 ) | ||||
|                 workoutViewModel.insert(newWorkout) | ||||
| 
 | ||||
|                 Toast.makeText(this, "Упражнение сохранено", Toast.LENGTH_SHORT).show() | ||||
| 
 | ||||
|                 isSave = true | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         val button_on_main_all: Button = findViewById(R.id.btn_on_main_all) | ||||
| @ -71,10 +133,16 @@ class AddWorkout : AppCompatActivity() { | ||||
|         val Plus: ImageView = findViewById(R.id.add_set) | ||||
|         val Minus: ImageView = findViewById(R.id.del_set) | ||||
| 
 | ||||
|         val numExer: EditText = findViewById(R.id.num_exercise) | ||||
|         val PlusExer: ImageView = findViewById(R.id.add_set4) | ||||
|         val MinusExer: ImageView = findViewById(R.id.del_set4) | ||||
| 
 | ||||
| 
 | ||||
|         setupPlusMinus(timeInputRestSetAll, btnPlusTimeAll, btnMinusTimeAll, minValue = 5, maxValue = 600) | ||||
|         setupPlusMinus(setsInputAll, btnPlusSetsAll, btnMinusSetsAll, minValue = 1, maxValue = 20) | ||||
|         setupPlusMinus(timeInputRest, btnPlusTimeWor, btnMinusTimeWor, minValue = 5, maxValue = 600) | ||||
|         setupPlusMinus(timeWork, Plus, Minus, minValue = 5, maxValue = 600) | ||||
|         setupPlusMinus(numExer, PlusExer, MinusExer, minValue = 1, maxValue = 50) | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
|  | ||||
| @ -59,7 +59,8 @@ class AllTraining : AppCompatActivity() { | ||||
|                 val newExercise = Exercise( | ||||
|                     name_exercise = exerciseName, | ||||
|                     num_sets = numSets, | ||||
|                     rest_of_sets = restSets | ||||
|                     rest_of_sets = restSets, | ||||
|                     trainingId = 0 | ||||
|                 ) | ||||
|                 exerciseViewModel.insert(newExercise) | ||||
|                 Toast.makeText(this, "Упражнение сохранено", Toast.LENGTH_SHORT).show() | ||||
|  | ||||
| @ -7,6 +7,7 @@ import android.widget.Button | ||||
| import android.widget.EditText | ||||
| import android.widget.ImageButton | ||||
| import android.widget.ImageView | ||||
| import android.widget.Toast | ||||
| import androidx.activity.enableEdgeToEdge | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.core.view.ViewCompat | ||||
| @ -15,18 +16,30 @@ import androidx.lifecycle.ViewModelProvider | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.example.timert.data.adapter.ExerciseAdapter | ||||
| import com.example.timert.data.entity.Training | ||||
| import com.example.timert.data.viewModel.ExerciseViewModel | ||||
| import com.example.timert.data.viewModel.TrainingViewModel | ||||
| import com.example.timert.data.viewModel.WorkoutViewModel | ||||
| 
 | ||||
| class CreatingTraining : AppCompatActivity() { | ||||
| 
 | ||||
|     private lateinit var viewModel: ExerciseViewModel | ||||
| 
 | ||||
|     private lateinit var name_training: EditText | ||||
|     private lateinit var numSets: EditText | ||||
|     private lateinit var restSets: EditText | ||||
| 
 | ||||
|     private var isSave = false | ||||
| 
 | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|         enableEdgeToEdge() | ||||
|         setContentView(R.layout.activity_creating_training) | ||||
| 
 | ||||
|         ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> | ||||
|             val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) | ||||
|             v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) | ||||
|             insets | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -36,6 +49,10 @@ class CreatingTraining : AppCompatActivity() { | ||||
|         )[ExerciseViewModel::class.java] | ||||
| 
 | ||||
| 
 | ||||
|         name_training = findViewById(R.id.name_training) | ||||
|         numSets = findViewById(R.id.numbers_of_sets) | ||||
|         restSets = findViewById(R.id.rest_sets) | ||||
| 
 | ||||
|         val adapter = ExerciseAdapter { id -> | ||||
|             viewModel.deleteExerciseById(id) | ||||
|         } | ||||
| @ -50,6 +67,13 @@ class CreatingTraining : AppCompatActivity() { | ||||
|                 adapter.setExercises(it) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         val trainingViewModel = ViewModelProvider( | ||||
|             this, | ||||
|             ViewModelProvider.AndroidViewModelFactory.getInstance(application) | ||||
|         )[TrainingViewModel::class.java] | ||||
| 
 | ||||
| 
 | ||||
|         ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> | ||||
|             val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) | ||||
|             v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) | ||||
| @ -57,22 +81,46 @@ class CreatingTraining : AppCompatActivity() { | ||||
|         } | ||||
|         val buttonSave: Button = findViewById(R.id.btn_save) | ||||
|         buttonSave.setOnClickListener { | ||||
|             val name = name_training.text.toString() | ||||
|             val numS = numSets.text.toString() | ||||
|             val resS = restSets.text.toString() | ||||
| 
 | ||||
|             isSave=true | ||||
|             val intent = Intent(this, MainActivity::class.java) | ||||
|             startActivity(intent) | ||||
|             if (name.isBlank() || numS.isBlank() || resS.isBlank()) { | ||||
|                 Toast.makeText(this, "Заполните все поля", Toast.LENGTH_SHORT).show() | ||||
|             } else { | ||||
| 
 | ||||
|                 val sets = numS.toIntOrNull() | ||||
|                 val rest = resS.toIntOrNull() | ||||
| 
 | ||||
|                 if (sets == null || rest == null) { | ||||
|                     Toast.makeText(this, "Неверный формат чисел", Toast.LENGTH_SHORT).show() | ||||
|                     return@setOnClickListener | ||||
|                 } | ||||
| 
 | ||||
|                 val newTraining = Training( | ||||
|                     name = name, | ||||
|                     numSets = sets, | ||||
|                     restBetweenSets = rest) | ||||
| 
 | ||||
|                 trainingViewModel.insertTrainingAndLinkExercises(newTraining) | ||||
| 
 | ||||
|                 Toast.makeText(this, "Тренировка сохранена", Toast.LENGTH_SHORT).show() | ||||
| 
 | ||||
| 
 | ||||
|                 isSave = true | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         val timeInputRest: EditText = findViewById(R.id.rest_sets) | ||||
| 
 | ||||
|         val btnPlusTime: ImageView = findViewById(R.id.add_res) | ||||
|         val btnMinusTime: ImageView = findViewById(R.id.del_res) | ||||
| 
 | ||||
|         val setsInput: EditText = findViewById(R.id.numbers_of_sets) | ||||
| 
 | ||||
|         val btnPlusSets: ImageView = findViewById(R.id.add_set) | ||||
|         val btnMinusSets: ImageView = findViewById(R.id.del_set) | ||||
| 
 | ||||
|         setupPlusMinus(timeInputRest, btnPlusTime, btnMinusTime, minValue = 5, maxValue = 600) | ||||
|         setupPlusMinus(setsInput, btnPlusSets, btnMinusSets, minValue = 1, maxValue = 20) | ||||
|         setupPlusMinus(restSets, btnPlusTime, btnMinusTime, minValue = 5, maxValue = 600) | ||||
|         setupPlusMinus(numSets, btnPlusSets, btnMinusSets, minValue = 1, maxValue = 20) | ||||
|         val button_on_main: Button = findViewById(R.id.btn_on_main) | ||||
|         button_on_main.setOnClickListener { | ||||
|             if(isSave==false){ | ||||
|  | ||||
| @ -26,5 +26,11 @@ class History : AppCompatActivity() { | ||||
|         recyclerViewHistory.layoutManager = LinearLayoutManager(this) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         val button_on_main: Button = findViewById(R.id.btn_on_main) | ||||
|         button_on_main.setOnClickListener { | ||||
|             val intent = Intent(this, MainActivity::class.java) | ||||
|             startActivity(intent) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -2,18 +2,26 @@ package com.example.timert | ||||
| 
 | ||||
| import android.content.Intent | ||||
| import android.os.Bundle | ||||
| import android.util.Log | ||||
| import android.widget.Button | ||||
| import android.widget.Toast | ||||
| import androidx.activity.enableEdgeToEdge | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.core.view.ViewCompat | ||||
| import androidx.core.view.WindowInsetsCompat | ||||
| import androidx.lifecycle.ViewModelProvider | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.example.timert.com.example.timert.data.adapter.WorkoutAdapter | ||||
| import com.example.timert.data.TrainingItem | ||||
| import com.example.timert.data.adapter.TrainingAdapter | ||||
| import com.example.timert.data.viewModel.TrainingViewModel | ||||
| import com.example.timert.data.viewModel.WorkoutViewModel | ||||
| 
 | ||||
| 
 | ||||
| class MainActivity : AppCompatActivity() { | ||||
| 
 | ||||
| 
 | ||||
|     private lateinit var adapter: TrainingAdapter | ||||
|     private lateinit var workoutViewModel: WorkoutViewModel | ||||
|     private lateinit var trainingViewModel: TrainingViewModel | ||||
| 
 | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
| @ -24,6 +32,44 @@ class MainActivity : AppCompatActivity() { | ||||
|             v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) | ||||
|             insets | ||||
|         } | ||||
|         adapter = TrainingAdapter( | ||||
|             onDeleteWorkout = { id -> workoutViewModel.deleteWorkoutById(id) }, | ||||
|             onDeleteTraining = { id -> trainingViewModel.deleteTrainingById(id) } | ||||
|         ) | ||||
| 
 | ||||
|         val recyclerView = findViewById<RecyclerView>(R.id.workout) | ||||
|         recyclerView.layoutManager = LinearLayoutManager(this) | ||||
|         recyclerView.adapter = adapter | ||||
| 
 | ||||
|         workoutViewModel = ViewModelProvider(this)[WorkoutViewModel::class.java] | ||||
|         trainingViewModel = ViewModelProvider(this)[TrainingViewModel::class.java] | ||||
| 
 | ||||
|         // объединяем данные вручную | ||||
|         val combinedList = mutableListOf<TrainingItem>() | ||||
| 
 | ||||
|         workoutViewModel.allWorkouts.observe(this) { workouts -> | ||||
|             combinedList.clear() | ||||
|             combinedList.addAll(workouts.map { TrainingItem.WorkoutItem(it) }) | ||||
| 
 | ||||
|             trainingViewModel.allTrainingsWithExercises.value?.let { trainings -> | ||||
|                 combinedList.addAll(trainings.map { TrainingItem.TrainingWithExercisesItem(it) }) | ||||
|             } | ||||
| 
 | ||||
|             adapter.submitList(combinedList.toList()) | ||||
|         } | ||||
| 
 | ||||
|         trainingViewModel.allTrainingsWithExercises.observe(this) { trainings -> | ||||
|             combinedList.clear() | ||||
|             workoutViewModel.allWorkouts.value?.let { workouts -> | ||||
|                 combinedList.addAll(workouts.map { TrainingItem.WorkoutItem(it) }) | ||||
|             } | ||||
|             combinedList.addAll(trainings.map {TrainingItem.TrainingWithExercisesItem(it) }) | ||||
|             adapter.submitList(combinedList.toList()) | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         // Кнопки главной формы: | ||||
|         val settingsButton: Button = findViewById(R.id.settingsButton) | ||||
|  | ||||
| @ -2,7 +2,7 @@ package com.example.timert | ||||
| 
 | ||||
| import android.app.Application | ||||
| import androidx.room.Room | ||||
| import com.example.timert.AppDatabase | ||||
| import com.example.timert.com.example.timert.data.database.AppDatabase | ||||
| 
 | ||||
| class MyApplication : Application() { | ||||
|     companion object { | ||||
|  | ||||
| @ -0,0 +1,9 @@ | ||||
| package com.example.timert.data | ||||
| 
 | ||||
| import com.example.timert.com.example.timert.data.entity.Workout | ||||
| import com.example.timert.data.entity.Training | ||||
| 
 | ||||
| sealed class TrainingItem { | ||||
|     data class WorkoutItem(val workout: Workout) : TrainingItem() | ||||
|     data class TrainingWithExercisesItem(val trainingWithExercise: trainingWithExercise) : TrainingItem() | ||||
| } | ||||
| @ -1,18 +1,13 @@ | ||||
| package com.example.timert.data.adapter | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.Button | ||||
| import android.widget.ImageButton | ||||
| import android.widget.TextView | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.example.timert.R | ||||
| import com.example.timert.data.entity.Exercise | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.launch | ||||
| 
 | ||||
| 
 | ||||
| //class ExerciseAdapter internal constructor(context: Context):RecyclerView.Adapter<ExerciseAdapter.ExerciseViewHolder>(){ | ||||
|  | ||||
| @ -0,0 +1,80 @@ | ||||
| package com.example.timert.data.adapter | ||||
| 
 | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.Button | ||||
| import android.widget.ImageButton | ||||
| import android.widget.TextView | ||||
| import androidx.recyclerview.widget.DiffUtil | ||||
| import androidx.recyclerview.widget.ListAdapter | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.example.timert.R | ||||
| import com.example.timert.com.example.timert.data.entity.Workout | ||||
| import com.example.timert.data.TrainingItem | ||||
| import com.example.timert.data.entity.Training | ||||
| import com.example.timert.data.trainingWithExercise | ||||
| 
 | ||||
| class TrainingAdapter( private val onDeleteWorkout: (Int) -> Unit, | ||||
|                        private val onDeleteTraining: (Int) -> Unit | ||||
| ) : ListAdapter<TrainingItem, RecyclerView.ViewHolder>(DiffCallback())  { | ||||
| 
 | ||||
|     companion object { | ||||
|         private const val TYPE_WORKOUT = 0 | ||||
|         private const val TYPE_TRAINING_WITH_EXERCISES = 1 | ||||
|     } | ||||
| 
 | ||||
|     override fun getItemViewType(position: Int): Int { | ||||
|         return when (getItem(position)) { | ||||
|             is TrainingItem.WorkoutItem -> TYPE_WORKOUT | ||||
|             is TrainingItem.TrainingWithExercisesItem -> TYPE_TRAINING_WITH_EXERCISES | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||||
|         val inflater = LayoutInflater.from(parent.context) | ||||
|         val view = inflater.inflate(R.layout.training_item_layout, parent, false) // один layout | ||||
|         return when (viewType) { | ||||
|             TYPE_WORKOUT -> WorkoutViewHolder(view, onDeleteWorkout) | ||||
|             TYPE_TRAINING_WITH_EXERCISES -> TrainingViewHolder(view, onDeleteTraining) | ||||
|             else -> throw IllegalArgumentException("Invalid view type") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | ||||
|         when (val item = getItem(position)) { | ||||
|             is TrainingItem.WorkoutItem -> (holder as WorkoutViewHolder).bind(item.workout) | ||||
|             is TrainingItem.TrainingWithExercisesItem -> (holder as TrainingViewHolder).bind(item.trainingWithExercise) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     class WorkoutViewHolder(itemView: View, private val onDelete: (Int) -> Unit) : | ||||
|         RecyclerView.ViewHolder(itemView) { | ||||
|         fun bind(workout: Workout) { | ||||
|             itemView.findViewById<TextView>(R.id.training_text).text = workout.name | ||||
|             itemView.findViewById<ImageButton>(R.id.deleteButtonTraining).setOnClickListener { | ||||
|                 onDelete(workout.id) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     class TrainingViewHolder(itemView: View, private val onDelete: (Int) -> Unit) : | ||||
|         RecyclerView.ViewHolder(itemView) { | ||||
|         fun bind(trainingWithExercise: trainingWithExercise) { | ||||
|             itemView.findViewById<TextView>(R.id.training_text).text = trainingWithExercise.training.name | ||||
|             itemView.findViewById<ImageButton>(R.id.deleteButtonTraining).setOnClickListener { | ||||
|                 onDelete(trainingWithExercise.training.id) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     class DiffCallback : DiffUtil.ItemCallback<TrainingItem>() { | ||||
|         override fun areItemsTheSame(oldItem: TrainingItem, newItem: TrainingItem): Boolean { | ||||
|             return oldItem == newItem | ||||
|         } | ||||
| 
 | ||||
|         override fun areContentsTheSame(oldItem: TrainingItem, newItem: TrainingItem): Boolean { | ||||
|             return oldItem == newItem | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,48 @@ | ||||
| package com.example.timert.com.example.timert.data.adapter | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.ImageButton | ||||
| import android.widget.TextView | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.example.timert.R | ||||
| import com.example.timert.com.example.timert.data.entity.Workout | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| class WorkoutAdapter internal constructor(private val onDeleteClick: (Int) -> Unit | ||||
| ) : RecyclerView.Adapter<WorkoutAdapter.WorkoutViewHolder>() { | ||||
|     private var workouts: List<Workout> = emptyList() | ||||
| 
 | ||||
|     inner class WorkoutViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { | ||||
|         val textViewName: TextView = itemView.findViewById(R.id.training_text) | ||||
|         val deleteButton: ImageButton = itemView.findViewById(R.id.deleteButtonTraining) | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WorkoutViewHolder { | ||||
|         val itemView = LayoutInflater.from(parent.context) | ||||
|             .inflate(R.layout.training_item_layout, parent, false) | ||||
|         return WorkoutViewHolder(itemView) | ||||
|     } | ||||
| 
 | ||||
|     override fun onBindViewHolder(holder: WorkoutViewHolder, position: Int) { | ||||
|         val currentItem = workouts[position] | ||||
|         holder.textViewName.text = | ||||
|             "${currentItem.name}" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         holder.deleteButton.setOnClickListener { | ||||
|             onDeleteClick(currentItem.id) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun getItemCount() = workouts.size | ||||
| 
 | ||||
|     fun setWorkouts(workouts: List<Workout>) { | ||||
|         this.workouts = workouts | ||||
|         notifyDataSetChanged() | ||||
|     } | ||||
| } | ||||
| @ -6,11 +6,14 @@ import androidx.room.Delete | ||||
| import androidx.room.Insert | ||||
| import androidx.room.OnConflictStrategy | ||||
| import androidx.room.Query | ||||
| import androidx.room.Transaction | ||||
| import com.example.timert.data.entity.Exercise | ||||
| 
 | ||||
| 
 | ||||
| @Dao | ||||
| interface ExerciseDao { | ||||
| 
 | ||||
|     @Transaction | ||||
|     @Insert(onConflict = OnConflictStrategy.REPLACE) | ||||
|     suspend fun insert(exercise: Exercise) | ||||
| 
 | ||||
| @ -18,9 +21,9 @@ interface ExerciseDao { | ||||
|     fun getExercise(): LiveData<List<Exercise>> | ||||
| 
 | ||||
| 
 | ||||
|     //@Delete | ||||
|    // suspend fun delete(exercise: Exercise) | ||||
| 
 | ||||
|     @Query("DELETE FROM exercise_table WHERE id = :id") | ||||
|     suspend fun deleteById(id: Int) | ||||
| 
 | ||||
|     @Query("UPDATE exercise_table SET trainingId = :newTrainingId WHERE trainingId = 0") | ||||
|     suspend fun updateExercisesWithTrainingId(newTrainingId: Int) | ||||
| } | ||||
							
								
								
									
										41
									
								
								app/src/main/java/com/example/timert/data/dao/TrainingDao.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/src/main/java/com/example/timert/data/dao/TrainingDao.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| package com.example.timert.data.dao | ||||
| 
 | ||||
| import androidx.lifecycle.LiveData | ||||
| import androidx.room.Dao | ||||
| import androidx.room.Delete | ||||
| import androidx.room.Insert | ||||
| import androidx.room.OnConflictStrategy | ||||
| import androidx.room.Query | ||||
| import androidx.room.Transaction | ||||
| import com.example.timert.data.entity.Training | ||||
| import com.example.timert.data.trainingWithExercise | ||||
| 
 | ||||
| 
 | ||||
| @Dao | ||||
| interface TrainingDao { | ||||
| 
 | ||||
|     @Insert(onConflict = OnConflictStrategy.REPLACE) | ||||
|     suspend fun insertTraining(training: Training) : Long | ||||
| 
 | ||||
|     @Query("SELECT * FROM Training WHERE id = :trainingId") | ||||
|     fun getTrainingWithExercise(trainingId: Int): LiveData<trainingWithExercise> | ||||
| 
 | ||||
|     @Delete | ||||
|     fun deleteTraining(training: Training) | ||||
| 
 | ||||
|     @Query("SELECT * FROM training") | ||||
|     fun getAllTrainings(): LiveData<List<Training>> | ||||
| 
 | ||||
|     @Query("DELETE FROM training WHERE id = :id") | ||||
|     suspend fun deleteById(id: Int) | ||||
| 
 | ||||
|     @Query("SELECT * FROM training WHERE id = :trainingId") | ||||
|     fun getTrainingWithExercises(trainingId: Int): LiveData<trainingWithExercise> | ||||
|     @Transaction | ||||
|     @Query("SELECT * FROM training") | ||||
|     fun getAllTrainingsWithExercises(): LiveData<List<trainingWithExercise>> | ||||
| 
 | ||||
|     @Transaction | ||||
|     @Query("SELECT * FROM training") | ||||
|     fun getTrainingsWithExercises(): LiveData<List<trainingWithExercise>> | ||||
| } | ||||
| @ -1,22 +1,29 @@ | ||||
| package com.example.timert | ||||
| package com.example.timert.com.example.timert.data.dao | ||||
| 
 | ||||
| import androidx.lifecycle.LiveData | ||||
| import androidx.room.Dao | ||||
| import androidx.room.Insert | ||||
| import androidx.room.OnConflictStrategy | ||||
| import androidx.room.Query | ||||
| import androidx.room.Update | ||||
| import com.example.timert.com.example.timert.data.entity.Workout | ||||
| import com.example.timert.data.entity.Exercise | ||||
| 
 | ||||
| @Dao | ||||
| interface WorkoutDao { | ||||
| 
 | ||||
|     @Insert(onConflict = OnConflictStrategy.IGNORE) | ||||
|     suspend fun insertWorkout(workout: Workout): Long | ||||
| 
 | ||||
|     @Query("SELECT * FROM workouts") | ||||
|     suspend fun getAllWorkouts(): List<Workout> | ||||
|     fun getAllWorkouts(): LiveData<List<Workout>> | ||||
| 
 | ||||
|     @Query("SELECT * FROM workouts WHERE id = :workoutId") | ||||
|     suspend fun getWorkoutById(workoutId: Int): Workout? | ||||
| 
 | ||||
|     @Update | ||||
|     suspend fun updateWorkout(workout: Workout) | ||||
| 
 | ||||
|     @Query("DELETE FROM workouts WHERE id = :id") | ||||
|     suspend fun deleteById(id: Int) | ||||
| } | ||||
| @ -0,0 +1,43 @@ | ||||
| package com.example.timert.com.example.timert.data.database | ||||
| 
 | ||||
| import android.content.Context | ||||
| import androidx.room.Database | ||||
| import androidx.room.Room | ||||
| import androidx.room.RoomDatabase | ||||
| import com.example.timert.com.example.timert.data.dao.WorkoutDao | ||||
| import com.example.timert.com.example.timert.data.entity.Workout | ||||
| import com.example.timert.data.dao.ExerciseDao | ||||
| import com.example.timert.data.dao.TrainingDao | ||||
| import com.example.timert.data.entity.Exercise | ||||
| import com.example.timert.data.entity.Training | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| 
 | ||||
| @Database(entities = [Workout::class, Exercise::class, Training::class],   version = 3, exportSchema = false) | ||||
| abstract class AppDatabase : RoomDatabase() { | ||||
|     abstract fun workoutDao(): WorkoutDao | ||||
|     abstract fun trainingDao(): TrainingDao | ||||
|     abstract fun exerciseDao(): ExerciseDao | ||||
| 
 | ||||
|     companion object { | ||||
|         @Volatile | ||||
|         private var INSTANCE: AppDatabase? = null | ||||
|         fun getDatabase(context: Context): AppDatabase { | ||||
|             val tempInstance = INSTANCE | ||||
|             if (tempInstance != null) { | ||||
|                 return tempInstance | ||||
|             } | ||||
|             synchronized(this) { | ||||
|                 val instance = Room.databaseBuilder( | ||||
|                     context.applicationContext, | ||||
|                     AppDatabase::class.java, | ||||
|                     "workout_database" | ||||
|                 ) | ||||
|                     //.fallbackToDestructiveMigration() | ||||
|                     .build() | ||||
|                 INSTANCE = instance | ||||
|                 return instance | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,61 +0,0 @@ | ||||
| package com.example.timert.data.database | ||||
| 
 | ||||
| import android.content.Context | ||||
| import androidx.room.Database | ||||
| import androidx.room.Room | ||||
| import androidx.room.RoomDatabase | ||||
| import androidx.sqlite.db.SupportSQLiteDatabase | ||||
| import com.example.timert.data.dao.ExerciseDao | ||||
| import com.example.timert.data.entity.Exercise | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.launch | ||||
| 
 | ||||
| @Database(entities = [Exercise::class], version = 1, exportSchema = false) | ||||
| abstract class ExerciseDatabase:RoomDatabase(){ | ||||
|     abstract fun exerciseDao():ExerciseDao | ||||
| 
 | ||||
|    // private class ExerciseDatabaseCallback (private val scope: CoroutineScope) : RoomDatabase.Callback(){ | ||||
| 
 | ||||
|         //override fun onOpen(db: SupportSQLiteDatabase) { | ||||
|          //   super.onOpen(db) | ||||
|         //    INSTANCE?.let { database -> | ||||
|          //       scope.launch { | ||||
|          //           populateDatabase(database.exerciseDao()) | ||||
|            //     } | ||||
|           //  } | ||||
|        // } | ||||
|         //suspend fun populateDatabase(exerciseDao: ExerciseDao) { | ||||
|             // Delete all content here. | ||||
|             //exerciseDao.deleteAll() | ||||
|             // Add sample words. | ||||
|             //var exercise = Exercise(0, "training", 10, 45 ) | ||||
|            // exerciseDao.insert(exercise) | ||||
| 
 | ||||
|             // TODO: Add your own words! | ||||
|      //   } | ||||
|     //} | ||||
|     companion object { | ||||
|         @Volatile | ||||
|         private var INSTANCE: ExerciseDatabase? = null | ||||
|         fun getDatabase(context: Context, | ||||
|                         scope: CoroutineScope | ||||
|         ): ExerciseDatabase { | ||||
|             val tempInstance = INSTANCE | ||||
|             if (tempInstance != null) { | ||||
|                 return tempInstance | ||||
|             } | ||||
|             synchronized(this) { | ||||
|                 val instance = Room.databaseBuilder( | ||||
|                     context.applicationContext, | ||||
|                     ExerciseDatabase::class.java, | ||||
|                     "exercise_database" | ||||
|                 ) | ||||
|                     //.addCallback(ExerciseDatabaseCallback(scope)) | ||||
|                     .build() | ||||
|                 INSTANCE = instance | ||||
|                 return instance | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         } | ||||
| } | ||||
| @ -1,11 +1,15 @@ | ||||
| package com.example.timert.data.entity | ||||
| 
 | ||||
| import androidx.room.Entity | ||||
| import androidx.room.ForeignKey | ||||
| import androidx.room.Index | ||||
| import androidx.room.PrimaryKey | ||||
| 
 | ||||
| 
 | ||||
| @Entity(tableName = "exercise_table") | ||||
| @Entity(tableName = "exercise_table", | ||||
|     indices = [Index("trainingId")]) | ||||
| data class Exercise(@PrimaryKey(autoGenerate = true) val id: Int = 0, | ||||
|                     val name_exercise: String, | ||||
|                     val num_sets: Int, | ||||
|                     val rest_of_sets: Int) | ||||
|                     val rest_of_sets: Int, | ||||
|                     val trainingId: Int = 0) | ||||
|  | ||||
							
								
								
									
										12
									
								
								app/src/main/java/com/example/timert/data/entity/Training.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/src/main/java/com/example/timert/data/entity/Training.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| package com.example.timert.data.entity | ||||
| 
 | ||||
| import androidx.room.Entity | ||||
| import androidx.room.PrimaryKey | ||||
| 
 | ||||
| @Entity(tableName = "training") | ||||
| data class Training( | ||||
|     @PrimaryKey(autoGenerate = true) val id: Int = 0, | ||||
|     val name: String, | ||||
|     val numSets: Int, | ||||
|     val restBetweenSets: Int | ||||
| ) | ||||
| @ -1,17 +1,16 @@ | ||||
| package com.example.timert | ||||
| package com.example.timert.com.example.timert.data.entity | ||||
| import androidx.room.Entity | ||||
| import androidx.room.PrimaryKey | ||||
| 
 | ||||
| @Entity(tableName = "workouts") | ||||
| data class Workout( | ||||
|     @PrimaryKey(autoGenerate = true) | ||||
|     val id: Int = 0, | ||||
|     @PrimaryKey(autoGenerate = true) val id: Int = 0, | ||||
|     val name: String, | ||||
|     val numApproaches: Int, | ||||
|     val numExercises: Int, | ||||
|     val restBetweenExercises: Int, | ||||
|     val restBetweenApproaches: Int, | ||||
|     val exerciseDuration: Int, | ||||
|     val startTime: Long? = null, | ||||
|     val endTime: Long? = null | ||||
|     //val startTime: Long? = null, | ||||
|    // val endTime: Long? = null | ||||
| ) | ||||
| @ -0,0 +1,23 @@ | ||||
| package com.example.timert.data.repository | ||||
| 
 | ||||
| import androidx.lifecycle.LiveData | ||||
| import com.example.timert.data.dao.TrainingDao | ||||
| import com.example.timert.data.entity.Training | ||||
| import com.example.timert.data.trainingWithExercise | ||||
| 
 | ||||
| class TrainingRepository(private val trainingDao: TrainingDao) { | ||||
| 
 | ||||
|     val allTrainings: LiveData<List<Training>> = trainingDao.getAllTrainings() | ||||
|     val allTrainingsWithExercises: LiveData<List<trainingWithExercise>> = trainingDao.getTrainingsWithExercises() | ||||
| 
 | ||||
|     suspend fun insert(training: Training): Long { | ||||
|         return trainingDao.insertTraining(training) | ||||
|     } | ||||
| 
 | ||||
|     suspend fun delete(training: Training) = trainingDao.deleteTraining(training) | ||||
| 
 | ||||
|     suspend fun deleteTrainingById(id: Int) { | ||||
|         trainingDao.deleteById(id) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| package com.example.timert.data.repository | ||||
| 
 | ||||
| import androidx.lifecycle.LiveData | ||||
| import com.example.timert.com.example.timert.data.dao.WorkoutDao | ||||
| import com.example.timert.com.example.timert.data.entity.Workout | ||||
| 
 | ||||
| class WorkoutRepository (private val workoutDao: WorkoutDao){ | ||||
|     val allWorkout: LiveData<List<Workout>> = workoutDao.getAllWorkouts() | ||||
|     suspend fun insert(workout: Workout) { | ||||
|         workoutDao.insertWorkout(workout) | ||||
|     } | ||||
| 
 | ||||
|     suspend fun deleteWorkoutById(id: Int) { | ||||
|         workoutDao.deleteById(id) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,16 @@ | ||||
| package com.example.timert.data | ||||
| 
 | ||||
| import androidx.lifecycle.LiveData | ||||
| import androidx.room.Embedded | ||||
| import androidx.room.Relation | ||||
| import com.example.timert.data.entity.Exercise | ||||
| import com.example.timert.data.entity.Training | ||||
| 
 | ||||
| data class trainingWithExercise ( | ||||
|     @Embedded val training: Training, | ||||
|     @Relation( | ||||
|         parentColumn = "id", | ||||
|         entityColumn = "trainingId" | ||||
|     ) | ||||
|     val exercises: List<Exercise> | ||||
| ) | ||||
| @ -4,7 +4,7 @@ import android.app.Application | ||||
| import androidx.lifecycle.AndroidViewModel | ||||
| import androidx.lifecycle.LiveData | ||||
| import androidx.lifecycle.viewModelScope | ||||
| import com.example.timert.data.database.ExerciseDatabase | ||||
| import com.example.timert.com.example.timert.data.database.AppDatabase | ||||
| import com.example.timert.data.entity.Exercise | ||||
| import com.example.timert.data.repository.ExerciseRepository | ||||
| import kotlinx.coroutines.launch | ||||
| @ -14,7 +14,7 @@ class ExerciseViewModel(application: Application):AndroidViewModel(application){ | ||||
|     val allExercise: LiveData<List<Exercise>> | ||||
| 
 | ||||
|     init{ | ||||
|         val exercisesDao = ExerciseDatabase.getDatabase(application, viewModelScope).exerciseDao() | ||||
|         val exercisesDao = AppDatabase.getDatabase(application).exerciseDao() | ||||
|         repository = ExerciseRepository(exercisesDao) | ||||
|         allExercise = repository.allExercise | ||||
|     } | ||||
|  | ||||
| @ -0,0 +1,50 @@ | ||||
| package com.example.timert.data.viewModel | ||||
| 
 | ||||
| import android.app.Application | ||||
| import androidx.lifecycle.AndroidViewModel | ||||
| import androidx.lifecycle.LiveData | ||||
| import androidx.lifecycle.viewModelScope | ||||
| import com.example.timert.com.example.timert.data.database.AppDatabase | ||||
| import com.example.timert.data.entity.Training | ||||
| 
 | ||||
| import com.example.timert.data.repository.TrainingRepository | ||||
| import com.example.timert.data.trainingWithExercise | ||||
| 
 | ||||
| import kotlinx.coroutines.launch | ||||
| 
 | ||||
| class TrainingViewModel (application: Application): AndroidViewModel(application){ | ||||
| 
 | ||||
|     val allWorkouts: LiveData<List<Training>> | ||||
|     private val trainingDao = AppDatabase.getDatabase(application).trainingDao() | ||||
|     private val repository = TrainingRepository(trainingDao) | ||||
| 
 | ||||
|     val allTrainings: LiveData<List<Training>> = repository.allTrainings | ||||
|     val allTrainingsWithExercises: LiveData<List<trainingWithExercise>> = repository.allTrainingsWithExercises | ||||
| 
 | ||||
|     init{ | ||||
|         val trainingDao = AppDatabase.getDatabase(application).trainingDao() | ||||
| 
 | ||||
|         allWorkouts = repository.allTrainings | ||||
|     } | ||||
|     fun insert(training: Training) = viewModelScope.launch { | ||||
|         repository.insert(training) | ||||
|     } | ||||
| 
 | ||||
|     fun deleteTrainingById(id: Int) = viewModelScope.launch { | ||||
|         repository.deleteTrainingById(id) | ||||
|     } | ||||
| 
 | ||||
|     fun delete(training: Training) = viewModelScope.launch { | ||||
|         repository.delete(training) | ||||
|     } | ||||
| 
 | ||||
|     fun insertTrainingAndLinkExercises(training: Training) { | ||||
|         viewModelScope.launch { | ||||
|             val newId = repository.insert(training) // возвращает id | ||||
|             // теперь обновляем trainingId в упражнениях | ||||
| 
 | ||||
|             AppDatabase.getDatabase(getApplication()).exerciseDao() | ||||
|                 .updateExercisesWithTrainingId(newId.toInt()) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,28 @@ | ||||
| package com.example.timert.data.viewModel | ||||
| 
 | ||||
| import android.app.Application | ||||
| import androidx.lifecycle.AndroidViewModel | ||||
| import androidx.lifecycle.LiveData | ||||
| import androidx.lifecycle.viewModelScope | ||||
| import com.example.timert.com.example.timert.data.database.AppDatabase | ||||
| import com.example.timert.com.example.timert.data.entity.Workout | ||||
| import com.example.timert.data.repository.WorkoutRepository | ||||
| import kotlinx.coroutines.launch | ||||
| 
 | ||||
| class WorkoutViewModel(application: Application):AndroidViewModel(application){ | ||||
|     private val repository: WorkoutRepository | ||||
|     val allWorkouts: LiveData<List<Workout>> | ||||
| 
 | ||||
|     init{ | ||||
|         val workoutDao = AppDatabase.getDatabase(application).workoutDao() | ||||
|         repository = WorkoutRepository(workoutDao) | ||||
|         allWorkouts = repository.allWorkout | ||||
|     } | ||||
|     fun insert(workout: Workout) = viewModelScope.launch { | ||||
|         repository.insert(workout) | ||||
|     } | ||||
| 
 | ||||
|     fun deleteWorkoutById(id: Int) = viewModelScope.launch { | ||||
|         repository.deleteWorkoutById(id) | ||||
|     } | ||||
| } | ||||
| @ -31,198 +31,255 @@ | ||||
|             android:layout_marginTop="20dp" | ||||
|             android:ems="10" | ||||
|             android:inputType="text" | ||||
|             android:text="Тренировка 1" | ||||
|             android:text="Моя тренировка" | ||||
|             android:textAlignment="center" | ||||
|             android:textSize="20sp" /> | ||||
| 
 | ||||
|     </LinearLayout> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         android:id="@+id/setting_training" | ||||
|     <ScrollView | ||||
|         android:id="@+id/scrollView2" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="400dp" | ||||
|         android:layout_marginTop="10dp" | ||||
|         android:orientation="vertical" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginTop="8dp" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/frameLayout2" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/linearLayout" | ||||
|         tools:layout_editor_absoluteX="16dp"> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/textView6" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:text="Количество подходов" | ||||
|             android:textAlignment="center" | ||||
|             android:textSize="24sp" /> | ||||
|         tools:layout_editor_absoluteX="9dp"> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="60dp" | ||||
|             android:orientation="horizontal"> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/del_set3" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="37dp" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 app:srcCompat="@drawable/ic_remove_24px" /> | ||||
| 
 | ||||
|             <EditText | ||||
|                 android:id="@+id/numbers_of_sets_all" | ||||
|                 android:layout_width="3dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 android:ems="10" | ||||
|                 android:gravity="center" | ||||
|                 android:inputType="number" | ||||
|                 android:text="1" | ||||
|                 android:textSize="26sp" /> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/add_set3" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="37dp" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 app:srcCompat="@drawable/ic_add_24px" /> | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/textView8_all2" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:text="Отдых между подходами" | ||||
|             android:textAlignment="center" | ||||
|             android:textSize="24sp" /> | ||||
|             android:orientation="vertical"> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="60dp" | ||||
|             android:orientation="horizontal"> | ||||
|             <LinearLayout | ||||
|                 android:id="@+id/setting_training" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="match_parent" | ||||
|                 android:layout_marginTop="10dp" | ||||
|                 android:orientation="vertical"> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/del_res_set2" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="37dp" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 app:srcCompat="@drawable/ic_remove_24px" /> | ||||
|                 <TextView | ||||
|                     android:id="@+id/textView6" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:text="Количество подходов" | ||||
|                     android:textAlignment="center" | ||||
|                     android:textSize="24sp" /> | ||||
| 
 | ||||
|             <EditText | ||||
|                 android:id="@+id/rest_sets_all" | ||||
|                 android:layout_width="3dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 android:ems="10" | ||||
|                 android:gravity="center" | ||||
|                 android:inputType="number" | ||||
|                 android:text="5" | ||||
|                 android:textSize="26sp" /> | ||||
|                 <LinearLayout | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="60dp" | ||||
|                     android:orientation="horizontal"> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/add_res_set2" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="37dp" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 app:srcCompat="@drawable/ic_add_24px" /> | ||||
|                     <ImageView | ||||
|                         android:id="@+id/del_set3" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_remove_24px" /> | ||||
| 
 | ||||
|                     <EditText | ||||
|                         android:id="@+id/numbers_of_sets_all" | ||||
|                         android:layout_width="3dp" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         android:ems="10" | ||||
|                         android:gravity="center" | ||||
|                         android:inputType="number" | ||||
|                         android:text="1" | ||||
|                         android:textSize="26sp" /> | ||||
| 
 | ||||
|                     <ImageView | ||||
|                         android:id="@+id/add_set3" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_add_24px" /> | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/textView14" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:text="Количество упражнений" | ||||
|                     android:textAlignment="center" | ||||
|                     android:textSize="24sp" /> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="match_parent" | ||||
|                     android:orientation="horizontal"> | ||||
| 
 | ||||
|                     <ImageView | ||||
|                         android:id="@+id/del_set4" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_remove_24px" /> | ||||
| 
 | ||||
|                     <EditText | ||||
|                         android:id="@+id/num_exercise" | ||||
|                         android:layout_width="3dp" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         android:ems="10" | ||||
|                         android:gravity="center" | ||||
|                         android:inputType="number" | ||||
|                         android:text="1" | ||||
|                         android:textSize="26sp" /> | ||||
| 
 | ||||
|                     <ImageView | ||||
|                         android:id="@+id/add_set4" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_add_24px" /> | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/textView8_all2" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:text="Отдых между подходами" | ||||
|                     android:textAlignment="center" | ||||
|                     android:textSize="24sp" /> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:orientation="horizontal"> | ||||
| 
 | ||||
|                     <ImageView | ||||
|                         android:id="@+id/del_res_set2" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_remove_24px" /> | ||||
| 
 | ||||
|                     <EditText | ||||
|                         android:id="@+id/rest_sets_all" | ||||
|                         android:layout_width="3dp" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         android:ems="10" | ||||
|                         android:gravity="center" | ||||
|                         android:inputType="number" | ||||
|                         android:text="5" | ||||
|                         android:textSize="26sp" /> | ||||
| 
 | ||||
|                     <ImageView | ||||
|                         android:id="@+id/add_res_set2" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_add_24px" /> | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/textView5" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:text="Время работы" | ||||
|                     android:textAlignment="center" | ||||
|                     android:textSize="24sp" /> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="60dp" | ||||
|                     android:layout_marginBottom="20dp" | ||||
|                     android:orientation="horizontal"> | ||||
| 
 | ||||
|                     <ImageView | ||||
|                         android:id="@+id/del_set" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_remove_24px" /> | ||||
| 
 | ||||
|                     <EditText | ||||
|                         android:id="@+id/time_work_all" | ||||
|                         android:layout_width="3dp" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         android:ems="10" | ||||
|                         android:gravity="center" | ||||
|                         android:inputType="number" | ||||
|                         android:text="5" | ||||
|                         android:textSize="26sp" /> | ||||
| 
 | ||||
|                     <ImageView | ||||
|                         android:id="@+id/add_set" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_add_24px" /> | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|                 <TextView | ||||
|                     android:id="@+id/textView8_all" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:text="Отдых между упражнениями" | ||||
|                     android:textAlignment="center" | ||||
|                     android:textSize="24sp" /> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="60dp" | ||||
|                     android:orientation="horizontal"> | ||||
| 
 | ||||
|                     <ImageView | ||||
|                         android:id="@+id/del_res" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_remove_24px" /> | ||||
| 
 | ||||
|                     <EditText | ||||
|                         android:id="@+id/rest_workout_all" | ||||
|                         android:layout_width="3dp" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         android:ems="10" | ||||
|                         android:gravity="center" | ||||
|                         android:inputType="number" | ||||
|                         android:text="5" | ||||
|                         android:textSize="26sp" /> | ||||
| 
 | ||||
|                     <ImageView | ||||
|                         android:id="@+id/add_res" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="37dp" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_weight="1" | ||||
|                         app:srcCompat="@drawable/ic_add_24px" /> | ||||
| 
 | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|             </LinearLayout> | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/textView5" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:text="Время работы" | ||||
|             android:textAlignment="center" | ||||
|             android:textSize="24sp" /> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="60dp" | ||||
|             android:layout_marginBottom="20dp" | ||||
|             android:orientation="horizontal"> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/del_set" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="37dp" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 app:srcCompat="@drawable/ic_remove_24px" /> | ||||
| 
 | ||||
|             <EditText | ||||
|                 android:id="@+id/time_work_all" | ||||
|                 android:layout_width="3dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 android:ems="10" | ||||
|                 android:gravity="center" | ||||
|                 android:inputType="number" | ||||
|                 android:text="5" | ||||
|                 android:textSize="26sp" /> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/add_set" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="37dp" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 app:srcCompat="@drawable/ic_add_24px" /> | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/textView8_all" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:text="Отдых между упражнениями" | ||||
|             android:textAlignment="center" | ||||
|             android:textSize="24sp" /> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="60dp" | ||||
|             android:orientation="horizontal"> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/del_res" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="37dp" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 app:srcCompat="@drawable/ic_remove_24px" /> | ||||
| 
 | ||||
|             <EditText | ||||
|                 android:id="@+id/rest_workout_all" | ||||
|                 android:layout_width="3dp" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 android:ems="10" | ||||
|                 android:gravity="center" | ||||
|                 android:inputType="number" | ||||
|                 android:text="5" | ||||
|                 android:textSize="26sp" /> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 android:id="@+id/add_res" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="37dp" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:layout_weight="1" | ||||
|                 app:srcCompat="@drawable/ic_add_24px" /> | ||||
| 
 | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|     </LinearLayout> | ||||
|     </ScrollView> | ||||
| 
 | ||||
|     <FrameLayout | ||||
|         android:id="@+id/frameLayout2" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="60dp" | ||||
|         android:layout_marginTop="10dp" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/setting_training" | ||||
| 
 | ||||
|         app:layout_constraintBottom_toTopOf="@+id/linearLayout4" | ||||
|         tools:layout_editor_absoluteX="0dp"> | ||||
| 
 | ||||
|         <Button | ||||
| @ -239,9 +296,10 @@ | ||||
|     </FrameLayout> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         android:id="@+id/linearLayout4" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="60dp" | ||||
|         android:layout_marginBottom="35dp" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:orientation="horizontal" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|  | ||||
| @ -18,7 +18,7 @@ | ||||
|         app:layout_constraintHorizontal_bias="0.0" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:layout_constraintVertical_bias="0.0" /> | ||||
|         app:layout_constraintVertical_bias="1.0" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/settingsButton" | ||||
| @ -99,4 +99,16 @@ | ||||
| 
 | ||||
|     </androidx.cardview.widget.CardView> | ||||
| 
 | ||||
|     <androidx.recyclerview.widget.RecyclerView | ||||
|         android:id="@+id/workout" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="0dp" | ||||
|         android:layout_marginTop="20dp" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintHorizontal_bias="0.0" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/newTemplateCardView" | ||||
|         app:layout_constraintVertical_bias="0.0" /> | ||||
| 
 | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
							
								
								
									
										38
									
								
								app/src/main/res/layout/training_item_layout.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/src/main/res/layout/training_item_layout.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:layout_width="wrap_content" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:layout_gravity="center_horizontal" | ||||
|     android:layout_marginTop="4dp" | ||||
|     android:layout_marginBottom="4dp"> | ||||
| 
 | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         android:id="@+id/layout" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:background="@drawable/green_rectangle" | ||||
|         android:gravity="center" | ||||
|         android:orientation="horizontal" | ||||
|         android:paddingTop="8dp" | ||||
|         android:paddingBottom="8dp"> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/training_text" | ||||
|             android:layout_width="353dp" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="center" | ||||
|             android:gravity="center" | ||||
|             android:paddingTop="10dp" | ||||
|             android:paddingBottom="10dp" | ||||
|             android:text="Тренировка" | ||||
|             android:textColor="#000000" | ||||
|             android:textSize="18sp" /> | ||||
| 
 | ||||
|         <ImageButton | ||||
|             android:id="@+id/deleteButtonTraining" | ||||
|             android:layout_width="48dp" | ||||
|             android:layout_height="48dp" | ||||
|             android:background="@android:drawable/ic_menu_delete" /> | ||||
|     </LinearLayout> | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
| @ -1,17 +0,0 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:layout_margin="8dp" | ||||
|     app:cardCornerRadius="4dp"> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/textViewName" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:padding="16dp" | ||||
|         android:text="Workout Name" | ||||
|         android:textSize="18sp" /> | ||||
| 
 | ||||
| </androidx.cardview.widget.CardView> | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user