From 48a8fcefcc21ac6a506a384b220a635cf6a5d260 Mon Sep 17 00:00:00 2001 From: jpolo1224 Date: Mon, 24 Aug 2026 13:06:47 -0400 Subject: [PATCH] Second screen: give the cover a real box, say which RA mode is active FIT_CENTER only helps when there is a box to fit into. The cover cell was WRAP_CONTENT around an image, which gives the cell no definite height, so the art sized itself and spilled past the cell to be clipped by the tile outline -- the same cut-off cover, arrived at a different way. Box art is about 1.4 times as tall as it is wide, so the cell is now given that shape at the column width and the whole cover fits inside it. adjustViewBounds went with it; it fights a definite box rather than helping. The achievement tile showed a hardcore count and a casual count above the total, which reads as three unrelated numbers -- "0 next to the trophy, then another 0/64" -- and says nothing about which mode is actually active, which was the one thing it needed to say. It now names the mode, with the trophy for hardcore and the medal for casual, over unlocked-of-total. --- .../src/main/java/com/armsx2/SecondScreen.kt | 40 +++++++++++++------ .../app/src/main/java/com/armsx2/i18n/I18n.kt | 2 + 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/platforms/android/app/src/main/java/com/armsx2/SecondScreen.kt b/platforms/android/app/src/main/java/com/armsx2/SecondScreen.kt index fa8c1ca918..ccb439ecb7 100644 --- a/platforms/android/app/src/main/java/com/armsx2/SecondScreen.kt +++ b/platforms/android/app/src/main/java/com/armsx2/SecondScreen.kt @@ -495,8 +495,21 @@ object SecondScreen { val params = android.widget.GridLayout.LayoutParams().apply { width = 0 // 0 means "as tall as the text needs", which is what the panel always did. - height = if (fixedH > 0) (dp * fixedH).toInt() - else ViewGroup.LayoutParams.WRAP_CONTENT + // + // The cover is the exception: WRAP_CONTENT around an image gives the cell no + // definite height, so FIT_CENTER had no box to fit into and the art spilled + // past the cell and was clipped. Box art is about 1.4 times as tall as it is + // wide, so the cell is given that shape at the column width and the whole + // cover then fits inside it. + height = when { + fixedH > 0 -> (dp * fixedH).toInt() + tile == SecondScreenTile.COVER -> { + val cellW = (resources.displayMetrics.widthPixels - + (dp * 28).toInt()) / columns.coerceAtLeast(1) + (cellW * 1.4f).toInt() + } + else -> ViewGroup.LayoutParams.WRAP_CONTENT + } columnSpec = android.widget.GridLayout.spec( android.widget.GridLayout.UNDEFINED, 1, 1f, ) @@ -583,7 +596,6 @@ object SecondScreen { // logo and the title on them. Fitting shows the whole cover and letterboxes it // against the tile background instead. scaleType = android.widget.ImageView.ScaleType.FIT_CENTER - adjustViewBounds = true } // A label UNDER the image rather than instead of it. With no game, or before the // fetch lands, an empty box is indistinguishable from a broken tile -- and this tile @@ -990,7 +1002,7 @@ object SecondScreen { private fun raPoints(): String { if (raItems.isEmpty()) return I18n.get("secondScreen.tile.raPoints") + "\n—" val earned = raItems.filter { it.unlocked }.sumOf { it.points } - return "šŸ† RA\n$earned/${raItems.sumOf { it.points }}" + return I18n.get("secondScreen.tile.raPoints") + "\n$earned/${raItems.sumOf { it.points }}" } /** @@ -1002,16 +1014,20 @@ object SecondScreen { * hardcore, and a hardcore unlock sets both, so the casual figure is deliberately the * softcore-ONLY count rather than the total. */ + /** + * Which mode you are in, then how many you have. + * + * The first attempt showed a hardcore count and a casual count above the total, which + * read as three unrelated numbers -- "šŸ†0" over "0/64" says nothing about which mode is + * active, and both being zero made it worse. What a glance actually wants is the mode + * you are playing in and your progress in it, so that is what it says. + */ private fun achievementSummary(): String { if (raItems.isEmpty()) return I18n.get("secondScreen.tile.achievements") + "\n—" - val unlocked = raItems.filter { it.unlocked } - val hardcore = unlocked.count { it.unlockedMask and 2 != 0 } - val casual = unlocked.size - hardcore - return buildString { - append("šŸ†").append(hardcore) - if (casual > 0) append(" šŸŽ–").append(casual) - append('\n').append(unlocked.size).append('/').append(raItems.size) - } + val hardcore = runCatching { NativeApp.isHardcorePersisted() }.getOrDefault(false) + val mode = if (hardcore) "šŸ† " + I18n.get("secondScreen.ra.hardcore") + else "šŸŽ– " + I18n.get("secondScreen.ra.casual") + return mode + "\n" + raItems.count { it.unlocked } + "/" + raItems.size } /** Session-only: which achievement ids were already unlocked when we last looked. */ diff --git a/platforms/android/app/src/main/java/com/armsx2/i18n/I18n.kt b/platforms/android/app/src/main/java/com/armsx2/i18n/I18n.kt index 47656f6324..ce8abacd63 100644 --- a/platforms/android/app/src/main/java/com/armsx2/i18n/I18n.kt +++ b/platforms/android/app/src/main/java/com/armsx2/i18n/I18n.kt @@ -1703,6 +1703,8 @@ private val BASE_EN: Map = mapOf( "touch.editor.scopeGlobal" to "Editing Global Default touch layout", "touch.editor.show" to "Show", "touch.editor.tapHoldOff" to "Tap-Hold Off", + "secondScreen.ra.hardcore" to "Hardcore", + "secondScreen.ra.casual" to "Casual", "secondScreen.tile.cover" to "Cover", "secondScreen.tile.raPoints" to "RA points", "secondScreen.tile.raRecent" to "Latest unlock",