class
WorkoutSetFragment : Fragment(), WorkoutSetInfoListener,
MaterialButtonToggleGroup.OnButtonCheckedListener {
private
var _binding: FragmentWorkoutSetBinding? =
null
private
val binding get() = _binding!!
private
val workoutViewModel: WorkoutViewModel by navGraphViewModels(R.id.mobile_navigation)
private
val workoutSetViewModel: WorkoutSetViewModel by viewModels()
override fun onDestroyView() {
super
.onDestroyView()
_binding =
null
}
override fun onStop() {
super
.onStop()
workoutSetViewModel.onStop()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentWorkoutSetBinding.inflate(inflater, container,
false
)
return
binding.root
}
private
val workoutSetInfoAdapter by lazy { WorkoutSetInfoAdapter(
this
) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super
.onViewCreated(view, savedInstanceState)
setupViews()
setupViewModel()
setupNavResult()
}
private
fun setupViews() {
binding.apply {
workoutBtn.setOnClickListener {
showWorkoutSelection()
}
kgBtn.isChecked =
true
unitGroup.addOnButtonCheckedListener(
this
@WorkoutSetFragment
)
addSetBtn.setOnClickListener {
workoutSetViewModel.onAddWorkoutSetInfo()
}
deleteSetBtn.setOnClickListener {
workoutSetViewModel.onDeleteWorkoutSetInfo()
}
addToLogBtn.setOnClickListener {
workoutSetViewModel.onSubmitWorkoutSet()
}
memoEdt.doAfterTextChanged {
if
(memoEdt.hasFocus()) {
workoutSetViewModel.onMemoChanged(it.toString())
}
}
detailRcv.adapter = workoutSetInfoAdapter
}
}
private
fun setupViewModel() {
workoutSetViewModel.workoutSetState.observe(viewLifecycleOwner, ::handleWorkoutSet)
lifecycleScope.launchWhenStarted {
workoutSetViewModel.event.collect(::handleWorkoutSetEvent)
}
}
private
fun setupNavResult() {
getNavResult<Workout> { workout ->
workoutSetViewModel.onWorkoutSelected(workout)
}
}
private
fun showWorkoutSelector() {
findNavController().navigate(R.id.action_writeDetailFragment_to_workoutSelectionFragment)
}
private
fun getWeightUnitByViewId(checkedId: Int): WeightUnit =
if
(checkedId == R.id.kgBtn) WeightUnit.KG
else
WeightUnit.LBS
private
fun handleWorkoutSet(workoutSet: WorkoutSet) {
if
(workoutSet == NullWorkoutSet)
return
bindAdapter(workoutSet.items)
bindWeightUnits(workoutSet.weightUnit)
bindWorkout(workoutSet.workout)
bindMemo(workoutSet.memo)
}
private
fun bindAdapter(items: List<WorkoutSetInfo>) {
workoutSetInfoAdapter.submitList(items)
}
private
fun bindWeightUnits(weightUnit: WeightUnit) {
binding.apply {
unitGroup.removeOnButtonCheckedListener(
this
@WorkoutSetFragment
)
kgBtn.isChecked = weightUnit == WeightUnit.KG
lbsBtn.isChecked = weightUnit == WeightUnit.LBS
unitGroup.addOnButtonCheckedListener(
this
@WorkoutSetFragment
)
}
}
private
fun bindWorkout(workout: Workout) {
binding.workoutBtn.text = workout.name
}
private
fun bindMemo(memo: String) {
binding.apply {
if
(memoEdt.text.toString() != memo) {
memoEdt.setText(memo)
}
}
}
private
fun handleWorkoutSetEvent(event: WorkoutSetEvent) {
when (event) {
is WorkoutSetEvent.WorkoutMissing -> showWorkoutSelector()
is WorkoutSetEvent.SubmitWorkoutSet -> submitWorkoutSet(event.workoutSet)
}
}
private
fun submitWorkoutSet(workoutSet: WorkoutSet) {
workoutViewModel.onAddWorkoutSet(workoutSet)
findNavController().popBackStack()
}
override fun onWeightChanged(item: WorkoutSetInfo, value: String) {
val weight = value.toIntOrNull() ?:
return
workoutSetViewModel.onWeightChanged(item.copy(weight = weight))
}
override fun onRepsChanged(item: WorkoutSetInfo, value: String) {
val reps = value.toIntOrNull() ?:
return
workoutSetViewModel.onRepsChanged(item.copy(reps = reps))
}
override fun onButtonChecked(
group: MaterialButtonToggleGroup?,
checkedId: Int,
isChecked: Boolean
) {
workoutSetViewModel.onUnitSelected(getWeightUnitByViewId(checkedId))
}
}
inline fun <T> Fragment.getNavResult(
key: String = NAV_RESULT_KEY,
crossinline onResult: (T) -> Unit,
) {
findNavController().currentBackStackEntry?.also { stack ->
stack.savedStateHandle.getLiveData<T>(key)
.observe(
viewLifecycleOwner,
Observer { result ->
onResult(result)
stack.savedStateHandle.remove<T>(key)
}
)
}
}
fun <T> Fragment.setNavResult(data: T, key: String = NAV_RESULT_KEY) {
findNavController().previousBackStackEntry?.also { stack ->
stack.savedStateHandle[key] = data
}
}