diff --git a/AGENTS.md b/AGENTS.md index 9ad4005..cd64391 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -69,7 +69,7 @@ Repository: `ssh://git@git.stinnesbeck.com:2222/nils/mg4.git` (remote `origin`), | Tab | Contents | |---|---| -| Overview | value tiles (battery, range, range/usage/energy since start, 5-min averages of range, usage, power, speed), vehicle info (odometer, lease allowance and the odometer against it), tyre pressures; read every 0.2 s on a background thread. Styles (Settings → Overview style): Tiles, Gauges (`GaugeView` needles), Cockpit (`RingView` rings, `TraceView` power trace), Retro (`RetroView`, seven-segment VFD, classic or in the accent colour), Futuristic (`FlowView`, animated energy flow), Sci-fi (`SciFiView`, starship console), Cartoon (`CartoonView`), Blueprint (`BlueprintView`, top-view drawing with tyre pressures), MG (`OctagonView`, octagonal dials after the classic MG dashboards), and on `ClusterCanvasView`: Minimal, Terminal, Aviation, Nixie tubes, Chronograph; the drawn styles share `ClusterValues` | +| Overview | value tiles (battery, range, range/usage/energy since start, 5-min averages of range, usage, power, speed), vehicle info (odometer, lease allowance and the odometer against it), tyre pressures; read every 0.2 s on a background thread. Styles (Settings → Overview style): Tiles, Gauges (`GaugeView` needles), Cockpit (`RingView` rings, `TraceView` power trace), Retro (`RetroView`, seven-segment VFD, classic or in the accent colour), Futuristic (`FlowView`, animated energy flow), Sci-fi (`SciFiView`, starship console), Cartoon (`CartoonView`), Blueprint (`BlueprintView`, top-view drawing with tyre pressures), MG (`OctagonView`, octagonal dials after the classic MG dashboards), and on `ClusterCanvasView`: Minimal, Terminal, Aviation, Nixie tubes, Chronograph; the drawn styles share `ClusterValues`. A button in the top-right corner hides the app's navigation for a full-width Overview (`PREF_OVERVIEW_FULLSCREEN`) | | 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 | diff --git a/README.md b/README.md index 02fb4a6..f0205c1 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ with the server using a token of its own, obtained by pairing with a phone (belo | Tab | What it shows | |---|---| -| **Overview** | Battery, range, power and speed; range, usage and energy since start; 5-minute averages of range, usage, power and speed; vehicle info (odometer, climate setpoint) and tyre pressures. Read five times a second. Looks to choose from in Settings → Overview style: Tiles, Gauges, Cockpit, Retro (classic turquoise or in your accent colour), Futuristic, Sci-fi, Cartoon, Blueprint, MG, Minimal, Terminal, Aviation, Nixie tubes and Chronograph | +| **Overview** | Battery, range, power and speed; range, usage and energy since start; 5-minute averages of range, usage, power and speed; vehicle info (odometer, climate setpoint) and tyre pressures. Read five times a second. Looks to choose from in Settings → Overview style: Tiles, Gauges, Cockpit, Retro (classic turquoise or in your accent colour), Futuristic, Sci-fi, Cartoon, Blueprint, MG, Minimal, Terminal, Aviation, Nixie tubes and Chronograph. The small button in the top-right corner hides the app's navigation for a full-width Overview; tap it again to bring it back | | **Consumption** | Lifetime, last 7 and 30 days, Trip A and B (distance, energy, average consumption and speed, SOC change), and a daily log of the last four months | | **Charging** | The current session (SOC, voltage, current, power, energy into the battery and from the grid, time, cost) and its SOC/power curve | | **Live data** | Live data on/off, ABRP credentials for sending directly from the car, upload frequency | diff --git a/SPECS.md b/SPECS.md index 685e6a5..1eddcef 100644 --- a/SPECS.md +++ b/SPECS.md @@ -131,6 +131,16 @@ 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.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 + "shrink" and a second tap brings the navigation back. Only on the Overview: other pages + always show the navigation and no button, swiping between pages still works, and coming back + to the Overview restores full width. Remembered (`overview_fullscreen`). The top-right corner + was chosen after looking at all fifteen styles (top left covered Tiles' "Battery"); Minimal's + clock moved left of it. Checked on the emulator: toggle, swipe away and back, restart, Tiles + and MG at full width (`screenshots/nilsmg4-2.27.0-overview-fullscreen.png`); no crash. Not + tried on the car. - 2026-10-24 — App 2.26.0 (branch `styles-retro-future`): five more Overview styles, chosen to differ in arrangement as much as in look, on a new base class `ClusterCanvasView` (values, easing, null-safe formatting, animating only while something moves and the view is shown). diff --git a/app/build.gradle b/app/build.gradle index 27ee57b..7aba6d2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,8 +34,8 @@ android { applicationId "com.stinnesbeck.nilsmg4" minSdk 27 targetSdk 36 - versionCode 120 - versionName "2.26.0" + versionCode 121 + versionName "2.27.0" // 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 3075415..f1bf575 100644 --- a/app/src/main/java/com/evsuite/abrp/MainActivity.java +++ b/app/src/main/java/com/evsuite/abrp/MainActivity.java @@ -182,7 +182,14 @@ public class MainActivity extends AppCompatActivity { // by the tick even when their page is off screen. pager.setOffscreenPageLimit(panes.length - 1); pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { - @Override public void onPageSelected(int position) { markCurrentPage(position); } + @Override public void onPageSelected(int position) { + markCurrentPage(position); + applyOverviewFullScreen(position); + } + }); + findViewById(R.id.overview_fullscreen).setOnClickListener(v -> { + prefs.edit().putBoolean(PREF_OVERVIEW_FULLSCREEN, !prefs.getBoolean(PREF_OVERVIEW_FULLSCREEN, false)).apply(); + applyOverviewFullScreen(pager.getCurrentItem()); }); for (int i = 0; i < TAB_IDS.length; i++) { @@ -192,6 +199,25 @@ public class MainActivity extends AppCompatActivity { findViewById(TAB_IDS[i]).setOnClickListener(v -> pager.setCurrentItem(index, false)); } markCurrentPage(pager.getCurrentItem()); + applyOverviewFullScreen(pager.getCurrentItem()); + } + + /** Whether the Overview hides the navigation (the button in its corner). */ + static final String PREF_OVERVIEW_FULLSCREEN = "overview_fullscreen"; + + /** + * The Overview full screen: the navigation hidden while the Overview is the page and the + * driver chose it; every other page always has its navigation, and swiping still works. + * The button only shows on the Overview, its icon saying what a tap does. + */ + private void applyOverviewFullScreen(int position) { + boolean overview = position == 0; + boolean full = overview && prefs.getBoolean(PREF_OVERVIEW_FULLSCREEN, false); + findViewById(R.id.nav_bar).setVisibility(full ? View.GONE : View.VISIBLE); + android.widget.ImageButton button = findViewById(R.id.overview_fullscreen); + button.setVisibility(overview ? View.VISIBLE : View.GONE); + button.setImageResource(full ? R.drawable.ic_fullscreen_exit : R.drawable.ic_fullscreen); + button.setContentDescription(getString(full ? R.string.overview_fullscreen_exit : R.string.overview_fullscreen_enter)); } /** diff --git a/app/src/main/java/com/evsuite/abrp/MinimalView.java b/app/src/main/java/com/evsuite/abrp/MinimalView.java index 1133784..44ec8bd 100644 --- a/app/src/main/java/com/evsuite/abrp/MinimalView.java +++ b/app/src/main/java/com/evsuite/abrp/MinimalView.java @@ -67,7 +67,8 @@ final class MinimalView extends ClusterCanvasView { // Corners: power and the clock; bottom middle: usage. text(c, fmt(v.powerKw, "%.1f kW", "— kW"), 8f * dp, 30f * dp, 20f * dp, grey, Paint.Align.LEFT); - text(c, v.clock.isEmpty() ? "—" : v.clock, w - 8f * dp, 30f * dp, 20f * dp, grey, Paint.Align.RIGHT); + // Left of the full-screen button, which sits in the top-right corner. + text(c, v.clock.isEmpty() ? "—" : v.clock, w - 72f * dp, 30f * dp, 20f * dp, grey, Paint.Align.RIGHT); text(c, fmt(v.usage5Min, "%.1f kWh/100 km", "— kWh/100 km"), w / 2f, h * 0.86f, 16f * dp, grey, Paint.Align.CENTER); // The battery: a hairline along the bottom, filled to the charge. diff --git a/app/src/main/java/com/evsuite/abrp/TerminalView.java b/app/src/main/java/com/evsuite/abrp/TerminalView.java index dd88f1d..c33e674 100644 --- a/app/src/main/java/com/evsuite/abrp/TerminalView.java +++ b/app/src/main/java/com/evsuite/abrp/TerminalView.java @@ -41,9 +41,10 @@ final class TerminalView extends ClusterCanvasView { // About 14 rows at 1.32 em each plus margins; monospace is about 0.6 em wide and the // longest row about 58 characters. - float size = Math.min(h / 19.5f, w / 38f); + float x = 16f * dp; + float size = Math.min(h / 19.5f, (w - x) / 38f); text.setTextSize(size); - float line = size * 1.32f, x = 16f * dp, y = 12f * dp + line; + float line = size * 1.32f, y = 12f * dp + line; String gear = gearRow(); print(c, "nils@mg4:~$ watch -n 0.2 vehicle-status", x, y, dim); diff --git a/app/src/main/res/drawable/bg_fullscreen_button.xml b/app/src/main/res/drawable/bg_fullscreen_button.xml new file mode 100644 index 0000000..09b553a --- /dev/null +++ b/app/src/main/res/drawable/bg_fullscreen_button.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_fullscreen.xml b/app/src/main/res/drawable/ic_fullscreen.xml new file mode 100644 index 0000000..83df4db --- /dev/null +++ b/app/src/main/res/drawable/ic_fullscreen.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_fullscreen_exit.xml b/app/src/main/res/drawable/ic_fullscreen_exit.xml new file mode 100644 index 0000000..c568eb4 --- /dev/null +++ b/app/src/main/res/drawable/ic_fullscreen_exit.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/layout-w1000dp/activity_main.xml b/app/src/main/res/layout-w1000dp/activity_main.xml index 2b9014b..58455d8 100644 --- a/app/src/main/res/layout-w1000dp/activity_main.xml +++ b/app/src/main/res/layout-w1000dp/activity_main.xml @@ -2,7 +2,7 @@ - + @@ -16,7 +16,11 @@ - + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ea0f520..8f5fa92 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -2,8 +2,12 @@ - - + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 73fe13b..1697fda 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -131,6 +131,8 @@ Cartoon Blueprint MG + Overview full screen: hide the navigation + Show the navigation again Minimal Terminal Aviation diff --git a/screenshots/nilsmg4-2.27.0-overview-fullscreen.png b/screenshots/nilsmg4-2.27.0-overview-fullscreen.png new file mode 100644 index 0000000..8931fd8 Binary files /dev/null and b/screenshots/nilsmg4-2.27.0-overview-fullscreen.png differ