From f3bfa5650bb5bff07240e6531ba10e014c42dca7 Mon Sep 17 00:00:00 2001 From: cmclark00 Date: Mon, 24 Mar 2025 17:06:24 -0400 Subject: [PATCH] Fix conversion display issues and remove annoying toast notifications --- .../tetristats/ui/entry/EntryFragment.kt | 43 ++++++++----------- .../tetristats/ui/entry/EntryViewModel.kt | 39 +++++++++++++---- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/accidentalproductions/tetristats/ui/entry/EntryFragment.kt b/app/src/main/java/com/accidentalproductions/tetristats/ui/entry/EntryFragment.kt index 338552e..5e2c8f5 100644 --- a/app/src/main/java/com/accidentalproductions/tetristats/ui/entry/EntryFragment.kt +++ b/app/src/main/java/com/accidentalproductions/tetristats/ui/entry/EntryFragment.kt @@ -17,6 +17,9 @@ class EntryFragment : Fragment() { private val binding get() = _binding!! private val viewModel: EntryViewModel by viewModels { EntryViewModelFactory(requireActivity().application) } private lateinit var equivalentScoreAdapter: EquivalentScoreAdapter + + // Flag to track if we already showed the requirements toast + private var hasShownRequirementsToast = false override fun onCreateView( inflater: LayoutInflater, @@ -35,8 +38,7 @@ class EntryFragment : Fragment() { setupSubmitButton() setupAutoAnalysis() - // Check if we should show conversions on startup - viewModel.checkConversionCriteria() + // Don't need to check on startup anymore - being handled by ViewModel } private fun setupGameVersionDropdown() { @@ -67,19 +69,7 @@ class EntryFragment : Fragment() { // Observe if we should show conversions viewModel.showConversion.observe(viewLifecycleOwner) { shouldShow -> - if (!shouldShow) { - // Hide analysis card if we don't meet criteria - binding.cardAnalysisResults.visibility = View.GONE - - // Also show a message that not enough scores have been entered - if (viewModel.lastSubmittedGame.value != null) { - Toast.makeText( - context, - "Enter at least 3 scores across 2 different games to see conversions", - Toast.LENGTH_LONG - ).show() - } - } + // No need to show toast here - we'll do it only after score submission } // Only setup equivalence UI when we have scores @@ -112,11 +102,13 @@ class EntryFragment : Fragment() { // Observe last submitted score details viewModel.lastSubmittedGame.observe(viewLifecycleOwner) { game -> // Only continue if showConversion is true - if (viewModel.showConversion.value != true) return@observe + if (viewModel.showConversion.value != true) { + binding.cardAnalysisResults.visibility = View.GONE + return@observe + } viewModel.lastSubmittedScore.value?.let { score -> binding.textViewOriginalScore.text = "Your $game score of ${"%,d".format(score)} is equivalent to:" - binding.cardAnalysisResults.visibility = View.VISIBLE // Get the list of games with scores val playedGames = viewModel.gamesWithScores.value ?: listOf() @@ -124,6 +116,7 @@ class EntryFragment : Fragment() { // Make sure we don't show the source game in the equivalent dropdown val filteredGames = playedGames.filter { it != game } if (filteredGames.isNotEmpty()) { + binding.cardAnalysisResults.visibility = View.VISIBLE val filteredAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, filteredGames) binding.autoCompleteEquivalentGame.setAdapter(filteredAdapter) @@ -133,11 +126,6 @@ class EntryFragment : Fragment() { } else { // If no other games to convert to, hide the card binding.cardAnalysisResults.visibility = View.GONE - Toast.makeText( - context, - "Add scores for other games to see conversions", - Toast.LENGTH_LONG - ).show() } } } @@ -171,8 +159,15 @@ class EntryFragment : Fragment() { ) clearInputs() - // Only scroll down if we're going to show conversions - if (viewModel.showConversion.value == true) { + // Check after submission if we should show requirements toast + if (viewModel.showConversion.value == false) { + Toast.makeText( + context, + "Enter at least 3 scores across 2 different games to see conversions", + Toast.LENGTH_LONG + ).show() + } else { + // Only scroll down if we're going to show conversions binding.root.post { binding.root.fullScroll(View.FOCUS_DOWN) } diff --git a/app/src/main/java/com/accidentalproductions/tetristats/ui/entry/EntryViewModel.kt b/app/src/main/java/com/accidentalproductions/tetristats/ui/entry/EntryViewModel.kt index 30fc865..13853b7 100644 --- a/app/src/main/java/com/accidentalproductions/tetristats/ui/entry/EntryViewModel.kt +++ b/app/src/main/java/com/accidentalproductions/tetristats/ui/entry/EntryViewModel.kt @@ -1,6 +1,7 @@ package com.accidentalproductions.tetristats.ui.entry import android.app.Application +import android.util.Log import androidx.lifecycle.* import com.accidentalproductions.tetristats.TetriStatsApplication import com.accidentalproductions.tetristats.data.Score @@ -42,6 +43,17 @@ class EntryViewModel(application: Application) : AndroidViewModel(application) { val lastSubmittedGame: LiveData = _lastSubmittedGame val lastSubmittedScore: LiveData = _lastSubmittedScore val showConversion: LiveData = _showConversion + + init { + // Set up observers to update conversion criteria whenever relevant data changes + gamesWithScores.observeForever { + checkConversionCriteria() + } + + totalScoreCount.observeForever { + checkConversionCriteria() + } + } fun getScoresForGame(gameVersion: String): LiveData> { return scoreDao.getScoresForGame(gameVersion) @@ -55,13 +67,16 @@ class EntryViewModel(application: Application) : AndroidViewModel(application) { * Check if we should show conversions based on score count and game count */ fun checkConversionCriteria() { - viewModelScope.launch { - val scoreCount = totalScoreCount.value ?: 0 - val gameCount = gamesWithScores.value?.size ?: 0 - - // Only show conversions if there are at least 3 scores across at least 2 games - _showConversion.postValue(scoreCount >= 3 && gameCount >= 2) - } + val scoreCount = totalScoreCount.value ?: 0 + val gameCount = gamesWithScores.value?.size ?: 0 + + // Only show conversions if there are at least 3 scores across at least 2 games + val shouldShow = scoreCount >= 3 && gameCount >= 2 + + // For debugging + Log.d("TetriStats", "Checking conversion criteria: scores=$scoreCount, games=$gameCount, shouldShow=$shouldShow") + + _showConversion.postValue(shouldShow) } fun insertScore( @@ -85,8 +100,7 @@ class EntryViewModel(application: Application) : AndroidViewModel(application) { _lastSubmittedGame.postValue(gameVersion) _lastSubmittedScore.postValue(score) - // Check if we should show conversions - checkConversionCriteria() + // The criteria check will happen automatically through the observers in init // Only generate equivalent scores if we meet the criteria if (_showConversion.value == true) { @@ -141,6 +155,13 @@ class EntryViewModel(application: Application) : AndroidViewModel(application) { } } } + + override fun onCleared() { + super.onCleared() + // Remove our observers to prevent leaks + gamesWithScores.removeObserver { checkConversionCriteria() } + totalScoreCount.removeObserver { checkConversionCriteria() } + } } class EntryViewModelFactory(private val application: Application) : ViewModelProvider.Factory {