From bc715fbc252257bd58e8fc4a084d0239e5f8220e Mon Sep 17 00:00:00 2001 From: Quildra Date: Mon, 4 Aug 2025 18:13:22 +0100 Subject: [PATCH] feat: enhance history expanded view to match drawer details MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Updated expanded view to show all Pokemon data fields like the drawer - Added comprehensive data sections: Pokemon Info, Types, Base Stats, Properties, Origin, Ability & Moves, Additional - Implemented multi-column layouts: two-column, three-column, checkbox rows, and mixed rows - Added visual elements: checkboxes (☑/☐), section headers, proper spacing - Improved data presentation with consistent formatting and organization - Enhanced layout helper methods for complex data display Data sections now include: - Pokemon Info: Species, Dex #, Nickname, Gender, Level, Nature - Types: Primary/Secondary types, Tera type - Base Stats: HP, ATK, DEF, SP.ATK, SP.DEF, SPEED (when available) - Properties: Shiny ✨, Alpha 🅰, Favorited ⭐, Pokeball type - Origin: Game source, Language, Original Trainer info - Ability & Moves: Pokemon ability and move list (up to 4) - Additional: Stamps, Labels, Marks (when present) The expanded view now provides the same comprehensive information as the ResultsBottomDrawer for consistent user experience. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../pokegoalshelper/ui/HistoryAdapter.kt | 328 ++++++++++++++++-- 1 file changed, 306 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/quillstudios/pokegoalshelper/ui/HistoryAdapter.kt b/app/src/main/java/com/quillstudios/pokegoalshelper/ui/HistoryAdapter.kt index 36962cd..e404b78 100644 --- a/app/src/main/java/com/quillstudios/pokegoalshelper/ui/HistoryAdapter.kt +++ b/app/src/main/java/com/quillstudios/pokegoalshelper/ui/HistoryAdapter.kt @@ -304,31 +304,111 @@ class HistoryAdapter( private fun addPokemonInfoViews(pokemonInfo: com.quillstudios.pokegoalshelper.PokemonInfo, context: Context) { - // Basic info section - addSectionHeader("Basic Info", context) - pokemonInfo.level?.let { addInfoRow("Level", it.toString(), context) } - pokemonInfo.gender?.let { addInfoRow("Gender", it, context) } - pokemonInfo.nature?.let { addInfoRow("Nature", it, context) } - - // Types section - if (pokemonInfo.primaryType != null || pokemonInfo.secondaryType != null) { - addSectionHeader("Types", context) - val typeText = when { - pokemonInfo.primaryType != null && pokemonInfo.secondaryType != null -> - "${pokemonInfo.primaryType} / ${pokemonInfo.secondaryType}" - pokemonInfo.primaryType != null -> pokemonInfo.primaryType - else -> "Unknown" + // Basic Pokemon Info Section + addSectionHeader("Pokemon Info", context) + addTwoColumnRow( + leftLabel = "Species", leftValue = pokemonInfo.species ?: "Unknown", + rightLabel = "Dex #", rightValue = pokemonInfo.nationalDexNumber?.let { "#$it" } ?: "N/A", + context = context + ) + + addTwoColumnRow( + leftLabel = "Nickname", leftValue = pokemonInfo.nickname ?: "None", + rightLabel = "Gender", rightValue = pokemonInfo.gender ?: "Unknown", + context = context + ) + + addTwoColumnRow( + leftLabel = "Level", leftValue = pokemonInfo.level?.toString() ?: "N/A", + rightLabel = "Nature", rightValue = pokemonInfo.nature ?: "Unknown", + context = context + ) + + // Types Section + addSectionHeader("Types", context) + val typeDisplay = when { + pokemonInfo.primaryType != null && pokemonInfo.secondaryType != null -> + "${pokemonInfo.primaryType} / ${pokemonInfo.secondaryType}" + pokemonInfo.primaryType != null -> pokemonInfo.primaryType + else -> "Unknown" + } + addTwoColumnRow( + leftLabel = "Type", leftValue = typeDisplay, + rightLabel = "Tera", rightValue = pokemonInfo.teraType ?: "N/A", + context = context + ) + + // Stats Section (if available) + pokemonInfo.stats?.let { stats -> + addSectionHeader("Base Stats", context) + addThreeColumnRow( + leftLabel = "HP", leftValue = stats.hp?.toString() ?: "?", + middleLabel = "ATK", middleValue = stats.attack?.toString() ?: "?", + rightLabel = "DEF", rightValue = stats.defense?.toString() ?: "?", + context = context + ) + addThreeColumnRow( + leftLabel = "SP.ATK", leftValue = stats.spAttack?.toString() ?: "?", + middleLabel = "SP.DEF", middleValue = stats.spDefense?.toString() ?: "?", + rightLabel = "SPEED", rightValue = stats.speed?.toString() ?: "?", + context = context + ) + } + + // Special Properties Section + addSectionHeader("Properties", context) + addCheckboxRow( + leftLabel = "Shiny", leftChecked = pokemonInfo.isShiny, + rightLabel = "Alpha", rightChecked = pokemonInfo.isAlpha, + context = context + ) + addMixedRow( + leftLabel = "Favorited", leftChecked = pokemonInfo.isFavorited, + rightLabel = "Pokeball", rightValue = pokemonInfo.pokeballType ?: "Unknown", + context = context + ) + + // Game Origin Section + addSectionHeader("Origin", context) + addTwoColumnRow( + leftLabel = "Game", leftValue = pokemonInfo.gameSource ?: "Unknown", + rightLabel = "Language", rightValue = pokemonInfo.language ?: "Unknown", + context = context + ) + + pokemonInfo.originalTrainerName?.let { trainerName -> + addTwoColumnRow( + leftLabel = "OT Name", leftValue = trainerName, + rightLabel = "OT ID", rightValue = pokemonInfo.originalTrainerId ?: "Unknown", + context = context + ) + } + + // Ability & Moves + pokemonInfo.ability?.let { ability -> + addSectionHeader("Ability & Moves", context) + addInfoRow("Ability", ability, context) + } + + if (pokemonInfo.moves.isNotEmpty()) { + if (pokemonInfo.ability == null) { + addSectionHeader("Moves", context) } - addInfoRow("Type", typeText, context) - pokemonInfo.teraType?.let { addInfoRow("Tera Type", it, context) } + addInfoRow("Moves", pokemonInfo.moves.take(4).joinToString(", "), context) } - // Special properties - if (pokemonInfo.isShiny || pokemonInfo.isAlpha || pokemonInfo.isFavorited) { - addSectionHeader("Properties", context) - if (pokemonInfo.isShiny) addInfoRow("Shiny", "✨ Yes", context) - if (pokemonInfo.isAlpha) addInfoRow("Alpha", "🅰 Yes", context) - if (pokemonInfo.isFavorited) addInfoRow("Favorited", "⭐ Yes", context) + // Additional Data + if (pokemonInfo.stamps.isNotEmpty() || pokemonInfo.labels.isNotEmpty() || pokemonInfo.marks.isNotEmpty()) { + addSectionHeader("Additional", context) + if (pokemonInfo.stamps.isNotEmpty()) { + addInfoRow("Stamps", pokemonInfo.stamps.joinToString(", "), context) + } + if (pokemonInfo.labels.isNotEmpty()) { + addInfoRow("Labels", pokemonInfo.labels.joinToString(", "), context) + } + if (pokemonInfo.marks.isNotEmpty()) { + addInfoRow("Marks", pokemonInfo.marks.joinToString(", "), context) + } } } @@ -392,6 +472,210 @@ class HistoryAdapter( expandedContainer.addView(row) } + private fun addTwoColumnRow( + leftLabel: String, leftValue: String, + rightLabel: String, rightValue: String, + context: Context + ) + { + val row = LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + setPadding(0, dpToPx(context, 2), 0, dpToPx(context, 2)) + } + + // Left column + val leftColumn = createColumnItem(leftLabel, leftValue, context) + leftColumn.layoutParams = LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, + 1f + ) + + // Right column + val rightColumn = createColumnItem(rightLabel, rightValue, context) + rightColumn.layoutParams = LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, + 1f + ).apply { + setMargins(dpToPx(context, 8), 0, 0, 0) + } + + row.addView(leftColumn) + row.addView(rightColumn) + expandedContainer.addView(row) + } + + private fun addThreeColumnRow( + leftLabel: String, leftValue: String, + middleLabel: String, middleValue: String, + rightLabel: String, rightValue: String, + context: Context + ) + { + val row = LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + setPadding(0, dpToPx(context, 2), 0, dpToPx(context, 2)) + } + + // Left column + val leftColumn = createColumnItem(leftLabel, leftValue, context) + leftColumn.layoutParams = LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, + 1f + ) + + // Middle column + val middleColumn = createColumnItem(middleLabel, middleValue, context) + middleColumn.layoutParams = LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, + 1f + ).apply { + setMargins(dpToPx(context, 4), 0, dpToPx(context, 4), 0) + } + + // Right column + val rightColumn = createColumnItem(rightLabel, rightValue, context) + rightColumn.layoutParams = LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, + 1f + ) + + row.addView(leftColumn) + row.addView(middleColumn) + row.addView(rightColumn) + expandedContainer.addView(row) + } + + private fun createColumnItem(label: String, value: String, context: Context): LinearLayout + { + return LinearLayout(context).apply { + orientation = LinearLayout.VERTICAL + gravity = android.view.Gravity.START + + val labelView = TextView(context).apply { + text = "$label:" + setTextSize(TypedValue.COMPLEX_UNIT_SP, 9f) + setTextColor(ContextCompat.getColor(context, android.R.color.darker_gray)) + } + + val valueView = TextView(context).apply { + text = value + setTextSize(TypedValue.COMPLEX_UNIT_SP, 11f) + setTextColor(ContextCompat.getColor(context, android.R.color.white)) + typeface = android.graphics.Typeface.DEFAULT_BOLD + } + + addView(labelView) + addView(valueView) + } + } + + private fun addCheckboxRow( + leftLabel: String, leftChecked: Boolean, + rightLabel: String, rightChecked: Boolean, + context: Context + ) + { + val row = LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + setPadding(0, dpToPx(context, 2), 0, dpToPx(context, 2)) + } + + // Left checkbox + val leftCheckbox = createCheckboxItem(leftLabel, leftChecked, context) + leftCheckbox.layoutParams = LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, + 1f + ) + + // Right checkbox + val rightCheckbox = createCheckboxItem(rightLabel, rightChecked, context) + rightCheckbox.layoutParams = LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, + 1f + ).apply { + setMargins(dpToPx(context, 8), 0, 0, 0) + } + + row.addView(leftCheckbox) + row.addView(rightCheckbox) + expandedContainer.addView(row) + } + + private fun addMixedRow( + leftLabel: String, leftChecked: Boolean, + rightLabel: String, rightValue: String, + context: Context + ) + { + val row = LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + setPadding(0, dpToPx(context, 2), 0, dpToPx(context, 2)) + } + + // Left checkbox + val leftCheckbox = createCheckboxItem(leftLabel, leftChecked, context) + leftCheckbox.layoutParams = LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, + 1f + ) + + // Right text item + val rightItem = createColumnItem(rightLabel, rightValue, context) + rightItem.layoutParams = LinearLayout.LayoutParams( + 0, + ViewGroup.LayoutParams.WRAP_CONTENT, + 1f + ).apply { + setMargins(dpToPx(context, 8), 0, 0, 0) + } + + row.addView(leftCheckbox) + row.addView(rightItem) + expandedContainer.addView(row) + } + + private fun createCheckboxItem(label: String, checked: Boolean, context: Context): LinearLayout + { + return LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + gravity = android.view.Gravity.CENTER_VERTICAL + + // Checkbox symbol + val checkboxView = TextView(context).apply { + text = if (checked) "☑" else "☐" + setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f) + setTextColor( + if (checked) ContextCompat.getColor(context, android.R.color.holo_green_light) + else ContextCompat.getColor(context, android.R.color.darker_gray) + ) + layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ).apply { + setMargins(0, 0, dpToPx(context, 6), 0) + } + } + + // Label + val labelView = TextView(context).apply { + text = label + setTextSize(TypedValue.COMPLEX_UNIT_SP, 11f) + setTextColor(ContextCompat.getColor(context, android.R.color.white)) + } + + addView(checkboxView) + addView(labelView) + } + } + private fun addDeleteButton(result: DetectionResult, position: Int, context: Context) { val deleteButton = Button(context).apply {