diff --git a/AGENTS.md b/AGENTS.md index cd64391..e5f961a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -73,7 +73,7 @@ Repository: `ssh://git@git.stinnesbeck.com:2222/nils/mg4.git` (remote `origin`), | Consumption / Charging | period totals, daily log, charging sessions and curve | | Live data | on/off, ABRP API key and user token, upload frequency | | Server | URL, pairing by QR, ingest token, installation ID (read-only), config import | -| Settings | full screen, voice key, tyre unit, accent colour, Overview style, battery, charging price, version, update check, install from USB, About | +| Settings | full screen, voice key, Overview style with the accent colour beside it (offered only for styles drawn in it, `OverviewStyle.usesAccent`), tyre unit, battery, charging price, version, update check, install from USB, About | | Logs | update log (every install step, with the platform's words), upload log | Key classes (`app/src/main/java/com/evsuite/abrp/`): `AbrpUploadService` (foreground service, diff --git a/SPECS.md b/SPECS.md index 1eddcef..a932e0f 100644 --- a/SPECS.md +++ b/SPECS.md @@ -131,6 +131,18 @@ tyre pressures, GPS (lat, lon, elevation, heading) and the is_* flags. It does * confirmed car facts, app structure, UI conventions, build/test/ship, documents. It replaces upstream's EVABRPUploader text. The test emulator is now in the flake: `nix run .#car-emulator` (Android 9 AOSP at 1920×720, 160 dpi; the car build installs as the system user — checked). +- 2026-10-24 — App 2.27.1 (branch `styles-retro-future`): Settings → Display rearranged: + Overview style first, the accent colour beside it, tyre pressure on its own row below. The + accent colour is only offered for styles drawn in it (Tiles, Gauges, Cockpit, Retro (accent + colour), Futuristic, MG, Minimal, Chronograph); for the styles with their own palette (Retro, + Sci-fi, Cartoon, Blueprint, Terminal, Aviation, Nixie tubes) the field is greyed out and + ignores taps, keeping the colour chosen before, and a line says "… has its own colours. To + change the accent colour, pick a style that uses it." The styles are now an enum, + `OverviewStyle` (stored names, `usesAccent`, the old `DASHBOARD` value; unit-tested), in place + of the string array. The style list is wider than its field so "Retro (accent colour)" fits. + Checked on the emulator: Tiles (accent open), Cartoon (greyed, tap ignored, note), back to + Tiles; the page fits without scrolling + (`screenshots/nilsmg4-2.27.1-settings-own-colours.png`). Not tried on the car. - 2026-10-24 — App 2.27.0 (branch `styles-retro-future`): the Overview can go full width. A small round button in its top-right corner (40 dp disc in a 72 dp touch area, over the pages) hides the app's navigation (sidebar, or the bottom bar on narrow screens); its icon turns to diff --git a/app/build.gradle b/app/build.gradle index 7aba6d2..3755015 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,8 +34,8 @@ android { applicationId "com.stinnesbeck.nilsmg4" minSdk 27 targetSdk 36 - versionCode 121 - versionName "2.27.0" + versionCode 122 + versionName "2.27.1" // Nothing about the server ships in the APK: its URL and ingest token are entered in // the app's Server tab (ServerConfig), and the database is only reachable by the server. diff --git a/app/src/main/java/com/evsuite/abrp/MainActivity.java b/app/src/main/java/com/evsuite/abrp/MainActivity.java index f1bf575..8b3190a 100644 --- a/app/src/main/java/com/evsuite/abrp/MainActivity.java +++ b/app/src/main/java/com/evsuite/abrp/MainActivity.java @@ -68,7 +68,7 @@ public class MainActivity extends AppCompatActivity { private OctagonView octagonView; /** The styles built on {@link ClusterCanvasView}, fed together. */ private final java.util.List canvasStyles = new java.util.ArrayList<>(); - /** The pane of each Overview style, by its index in {@link #OVERVIEW_STYLES}. */ + /** The pane of each Overview style, by its {@link OverviewStyle} ordinal. */ private View[] stylePanes; private View consumptionPane; private View chargingPane; @@ -1226,6 +1226,7 @@ public class MainActivity extends AppCompatActivity { prefs.edit().putString(AccentColor.PREF_KEY, colors[position].name()).apply(); recreate(); }); + applyAccentAvailability(); } /** Tyre pressure unit: display only, read on every refresh of the Overview. */ @@ -1479,35 +1480,45 @@ public class MainActivity extends AppCompatActivity { // ---------- Gauges (Overview style) ---------- - static final String PREF_OVERVIEW_STYLE = "overview_style"; + static final String PREF_OVERVIEW_STYLE = OverviewStyle.PREF_KEY; private GaugeView dashPower, dashSpeed, dashBattery; private BatteryBarView dashBatteryBar; private TextView dashGear, dashClimate, dashUsage, dashBatteryText; /** Kilometres since start, from the range estimator; null until it has a distance. */ private Double dashTripKm; - /** The stored values of the Overview styles, in the order of the drop-down. */ - private static final String[] OVERVIEW_STYLES = { "TILES", "GAUGES", "COCKPIT", "RETRO", "RETRO_ACCENT", "FUTURISTIC", - "SCIFI", "CARTOON", "BLUEPRINT", "MG", "MINIMAL", "TERMINAL", "AVIATION", "NIXIE", "CHRONOGRAPH" }; - - /** The chosen style's index in {@link #OVERVIEW_STYLES}; anything unknown is Tiles. */ - private int overviewStyle() { - String style = prefs.getString(PREF_OVERVIEW_STYLE, "TILES"); - if ("DASHBOARD".equals(style)) style = "GAUGES"; // its name before 2.22.3 - for (int i = 0; i < OVERVIEW_STYLES.length; i++) if (OVERVIEW_STYLES[i].equals(style)) return i; - return 0; + private OverviewStyle overviewStyle() { + return OverviewStyle.fromPref(prefs.getString(PREF_OVERVIEW_STYLE, null)); } private void applyOverviewStyle() { - int style = overviewStyle(); - for (View pane : stylePanes) pane.setVisibility(pane == stylePanes[style] ? View.VISIBLE : View.GONE); + OverviewStyle style = overviewStyle(); + for (View pane : stylePanes) pane.setVisibility(pane == stylePanes[style.ordinal()] ? View.VISIBLE : View.GONE); // Retro in either palette: one pane, the view told which. - retroView.setAccentPalette("RETRO_ACCENT".equals(OVERVIEW_STYLES[style])); + retroView.setAccentPalette(style == OverviewStyle.RETRO_ACCENT); + applyAccentAvailability(); } - /** The style drop-down; every style is fed on every reading, only the chosen one is shown. */ - private void bindOverviewStyle() { - String[] labels = { getString(R.string.overview_style_tiles), getString(R.string.overview_style_gauges), + /** + * The accent colour can only be picked for a style drawn in it; for the others the drop-down + * is greyed out (keeping the colour chosen before) and a line says why. + */ + private void applyAccentAvailability() { + if (settingsPane == null) return; + OverviewStyle style = overviewStyle(); + View field = settingsPane.findViewById(R.id.accent_field); + if (field == null) return; + field.setEnabled(style.usesAccent); + settingsPane.findViewById(R.id.accent_choices).setEnabled(style.usesAccent); + field.setAlpha(style.usesAccent ? 1f : 0.45f); + TextView note = settingsPane.findViewById(R.id.accent_note); + note.setVisibility(style.usesAccent ? View.GONE : View.VISIBLE); + note.setText(getString(R.string.accent_not_used, styleLabels()[style.ordinal()])); + } + + /** The drop-down's labels, by {@link OverviewStyle} ordinal. */ + private String[] styleLabels() { + return new String[] { getString(R.string.overview_style_tiles), getString(R.string.overview_style_gauges), getString(R.string.overview_style_cockpit), getString(R.string.overview_style_retro), getString(R.string.overview_style_retro_accent), getString(R.string.overview_style_futuristic), getString(R.string.overview_style_scifi), getString(R.string.overview_style_cartoon), @@ -1515,9 +1526,18 @@ public class MainActivity extends AppCompatActivity { getString(R.string.overview_style_minimal), getString(R.string.overview_style_terminal), getString(R.string.overview_style_aviation), getString(R.string.overview_style_nixie), getString(R.string.overview_style_chronograph) }; - bindChoices(settingsPane.findViewById(R.id.overview_style_choices), labels, overviewStyle(), + } + + /** The style drop-down; every style is fed on every reading, only the chosen one is shown. */ + private void bindOverviewStyle() { + OverviewStyle[] styles = OverviewStyle.values(); + com.google.android.material.textfield.MaterialAutoCompleteTextView field = + settingsPane.findViewById(R.id.overview_style_choices); + // Wider than its field, which shares a row with the accent colour: "Retro (accent colour)". + field.setDropDownWidth(Math.round(360 * getResources().getDisplayMetrics().density)); + bindChoices(field, styleLabels(), overviewStyle().ordinal(), position -> { - prefs.edit().putString(PREF_OVERVIEW_STYLE, OVERVIEW_STYLES[position]).apply(); + prefs.edit().putString(PREF_OVERVIEW_STYLE, styles[position].name()).apply(); applyOverviewStyle(); }); } diff --git a/app/src/main/java/com/evsuite/abrp/OverviewStyle.java b/app/src/main/java/com/evsuite/abrp/OverviewStyle.java new file mode 100644 index 0000000..a235623 --- /dev/null +++ b/app/src/main/java/com/evsuite/abrp/OverviewStyle.java @@ -0,0 +1,44 @@ +package com.evsuite.abrp; + +/** + * The Overview styles in the order of the Settings drop-down, the value each is stored as, and + * whether it is drawn in the chosen accent colour. Styles with their own fixed palette (Retro's + * display, the starship console, the cartoon, the blueprint, the terminal, the flight display, + * the nixie tubes) ignore it, so Settings only offers the accent colour for the others. Pure + * Java, unit-tested. + */ +enum OverviewStyle { + TILES(true), + GAUGES(true), + COCKPIT(true), + RETRO(false), + RETRO_ACCENT(true), + FUTURISTIC(true), + SCIFI(false), + CARTOON(false), + BLUEPRINT(false), + MG(true), + MINIMAL(true), + TERMINAL(false), + AVIATION(false), + NIXIE(false), + CHRONOGRAPH(true); + + static final String PREF_KEY = "overview_style"; + + /** Drawn in the accent colour, so the accent choice changes how it looks. */ + final boolean usesAccent; + + OverviewStyle(boolean usesAccent) { + this.usesAccent = usesAccent; + } + + /** The stored style; "DASHBOARD" (Gauges before 2.22.3) and anything unknown handled. */ + static OverviewStyle fromPref(String stored) { + if ("DASHBOARD".equals(stored)) return GAUGES; + for (OverviewStyle style : values()) { + if (style.name().equals(stored)) return style; + } + return TILES; + } +} diff --git a/app/src/main/res/layout-w1000dp/pane_settings.xml b/app/src/main/res/layout-w1000dp/pane_settings.xml index 50d6221..ac0111b 100644 --- a/app/src/main/res/layout-w1000dp/pane_settings.xml +++ b/app/src/main/res/layout-w1000dp/pane_settings.xml @@ -10,24 +10,31 @@ + - + + + + + + + + + + + + + + + + - - - - - - + - - - - diff --git a/app/src/main/res/layout/pane_settings.xml b/app/src/main/res/layout/pane_settings.xml index d78862d..5c8f743 100644 --- a/app/src/main/res/layout/pane_settings.xml +++ b/app/src/main/res/layout/pane_settings.xml @@ -7,18 +7,20 @@ + + + + + + + + + + - - - - - - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1697fda..144fae3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -131,6 +131,7 @@ Cartoon Blueprint MG + %1$s has its own colours. To change the accent colour, pick a style that uses it. Overview full screen: hide the navigation Show the navigation again Minimal diff --git a/app/src/test/java/com/evsuite/abrp/OverviewStyleTest.java b/app/src/test/java/com/evsuite/abrp/OverviewStyleTest.java new file mode 100644 index 0000000..51494fa --- /dev/null +++ b/app/src/test/java/com/evsuite/abrp/OverviewStyleTest.java @@ -0,0 +1,35 @@ +package com.evsuite.abrp; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** The Overview styles — pure JVM. */ +public class OverviewStyleTest { + + @Test + public void storedValuesRoundTrip() { + for (OverviewStyle style : OverviewStyle.values()) { + assertEquals(style, OverviewStyle.fromPref(style.name())); + } + } + + @Test + public void oldAndUnknownValues() { + assertEquals(OverviewStyle.GAUGES, OverviewStyle.fromPref("DASHBOARD")); + assertEquals(OverviewStyle.TILES, OverviewStyle.fromPref(null)); + assertEquals(OverviewStyle.TILES, OverviewStyle.fromPref("NOPE")); + } + + @Test + public void onlyStylesDrawnInTheAccentOfferIt() { + assertTrue(OverviewStyle.TILES.usesAccent); + assertTrue(OverviewStyle.RETRO_ACCENT.usesAccent); + assertTrue(OverviewStyle.MG.usesAccent); + assertFalse(OverviewStyle.RETRO.usesAccent); + assertFalse(OverviewStyle.CARTOON.usesAccent); + assertFalse(OverviewStyle.NIXIE.usesAccent); + } +} diff --git a/screenshots/nilsmg4-2.27.1-settings-own-colours.png b/screenshots/nilsmg4-2.27.1-settings-own-colours.png new file mode 100644 index 0000000..bc728d9 Binary files /dev/null and b/screenshots/nilsmg4-2.27.1-settings-own-colours.png differ