From 322ebcc4c0e7e8c34070900d14d129258dccffa9 Mon Sep 17 00:00:00 2001 From: TCFDONMEZ Date: Fri, 25 Sep 2026 14:01:57 +0300 Subject: [PATCH] feat: give window closing its own Pencereler tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The window switch sat on the Upload Service page, which implied a relationship that does not exist: closing windows needs no ABRP token, no GPS, no upload interval, and runs in its own service whether or not uploading is on. It is now a sixth page of the pager, between Araç and Wi-Fi. Splitting it in two while it moved, because the new page has room the card did not: the switch and status stay together, and the event log gets its own card, monospaced and no longer capped at four lines. setOffscreenPageLimit switches from a hardcoded 4 to panes.length - 1. It was already one short of the page count and would have gone stale again here. refreshWindowClose runs on the two-second tick and dereferences views on a page that may not be on screen, so the pager must not be free to detach them. Six tabs share the bar where five did. Widget.EV.NavTab already autosizes down to a 12sp floor, so the labels shrink rather than truncate. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 7 +- .../java/com/evsuite/abrp/MainActivity.java | 25 +++-- app/src/main/res/drawable/ic_tab_windows.xml | 13 +++ app/src/main/res/layout/activity_main.xml | 10 ++ app/src/main/res/layout/pane_service.xml | 48 ---------- app/src/main/res/layout/pane_windows.xml | 92 +++++++++++++++++++ app/src/main/res/values/strings.xml | 2 + 7 files changed, 136 insertions(+), 61 deletions(-) create mode 100644 app/src/main/res/drawable/ic_tab_windows.xml create mode 100644 app/src/main/res/layout/pane_windows.xml diff --git a/README.md b/README.md index b63c1b8..20d3a73 100644 --- a/README.md +++ b/README.md @@ -136,9 +136,10 @@ put them in a text file and tap **Import file** — see [Config file](#config-fi ## Configuration -On the **Upload Service** page, **Kapı açılınca camları kapat** enables the WinClose -integration independently of ABRP. It is off by default and restarts with the head unit -once enabled; no ABRP token, GPS permission, speed threshold or driving timer is needed. +On its own **Pencereler** page — not under Upload Service, since it shares nothing with +ABRP — **Kapı açılınca camları kapat** enables the WinClose integration. It is off by +default and restarts with the head unit once enabled; no ABRP token, GPS permission, +speed threshold or driving timer is needed. The integration is adapted from the sibling WinClose `WindowHardware.kt`: SWI69 `CarStateClient` door callback (transaction 6, value 0) triggers the VSM's diff --git a/app/src/main/java/com/evsuite/abrp/MainActivity.java b/app/src/main/java/com/evsuite/abrp/MainActivity.java index ca732ac..e27a19b 100644 --- a/app/src/main/java/com/evsuite/abrp/MainActivity.java +++ b/app/src/main/java/com/evsuite/abrp/MainActivity.java @@ -46,7 +46,8 @@ public class MainActivity extends AppCompatActivity { /** Top-bar tabs, in page order. Parallel to {@link #panes}. */ private static final int[] TAB_IDS = - { R.id.tabAbrp, R.id.tabService, R.id.tabVehicle, R.id.tabWifi, R.id.tabLog }; + { R.id.tabAbrp, R.id.tabService, R.id.tabVehicle, R.id.tabWindows, R.id.tabWifi, + R.id.tabLog }; // Status colours come from the palette, not from the Material swatches: #4CAF50 and // #F44336 sit around 4:1 on this background, which disappears behind a sunlit @@ -79,9 +80,10 @@ public class MainActivity extends AppCompatActivity { private View servicePane; private View logPane; private View vehiclePane; + private View windowsPane; private View wifiPane; - /** The five pages, in the order the top bar lists them. Parallel to {@link #TAB_IDS}. */ + /** The six pages, in the order the top bar lists them. Parallel to {@link #TAB_IDS}. */ private View[] panes; /** Wi-Fi page. The helper is the same one the upload service uses on its own tick. */ @@ -118,7 +120,7 @@ public class MainActivity extends AppCompatActivity { * Wires the top bar to the pager: every tab is a page, and every page is a tab. * * Each page has its own view type, so the pager asks for it once and keeps it: these - * three views are the activity's own, held in {@link #panes}, not rows to be recycled. + * views are the activity's own, held in {@link #panes}, not rows to be recycled. */ private void setUpPager() { ViewPager2 pager = findViewById(R.id.content); @@ -138,9 +140,11 @@ public class MainActivity extends AppCompatActivity { // state, exactly as they did when they were siblings in the layout. } }); - // All four stay alive. They are cheap, and the service switch, the call log and - // the vehicle readings are refreshed by the tick whether or not their page is on screen. - pager.setOffscreenPageLimit(4); + // All of them stay alive. They are cheap, and the service switch, the call log, the + // window-close status and the vehicle readings are refreshed by the tick whether or + // not their page is on screen — refreshWindowClose in particular dereferences views + // the pager would otherwise be free to detach. + pager.setOffscreenPageLimit(panes.length - 1); pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { markCurrentPage(position); } }); @@ -210,9 +214,10 @@ public class MainActivity extends AppCompatActivity { abrpPane = inflatePane(R.layout.pane_abrp); servicePane = inflatePane(R.layout.pane_service); vehiclePane = inflatePane(R.layout.pane_vehicle); + windowsPane = inflatePane(R.layout.pane_windows); wifiPane = inflatePane(R.layout.pane_wifi); logPane = inflatePane(R.layout.pane_log); - panes = new View[] { abrpPane, servicePane, vehiclePane, wifiPane, logPane }; + panes = new View[] { abrpPane, servicePane, vehiclePane, windowsPane, wifiPane, logPane }; bindVehiclePane(); bindWifiPane(); @@ -326,9 +331,9 @@ public class MainActivity extends AppCompatActivity { } private void bindWindowClose() { - windowCloseSwitch = servicePane.findViewById(R.id.window_close_switch); - windowCloseStatus = servicePane.findViewById(R.id.window_close_status); - windowCloseLog = servicePane.findViewById(R.id.window_close_log); + windowCloseSwitch = windowsPane.findViewById(R.id.window_close_switch); + windowCloseStatus = windowsPane.findViewById(R.id.window_close_status); + windowCloseLog = windowsPane.findViewById(R.id.window_close_log); windowCloseListener = (button, enabled) -> { prefs.edit().putBoolean(WindowCloseService.KEY_ENABLED, enabled).apply(); if (enabled) WindowCloseService.startIfEnabled(this); diff --git a/app/src/main/res/drawable/ic_tab_windows.xml b/app/src/main/res/drawable/ic_tab_windows.xml new file mode 100644 index 0000000..4d4babf --- /dev/null +++ b/app/src/main/res/drawable/ic_tab_windows.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index f2b3d5d..17ae262 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -72,6 +72,16 @@ android:text="@string/tab_vehicle" app:icon="@drawable/ic_tab_vehicle" /> + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 413478b..7ebd706 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,12 +12,14 @@ Bu sürüm araca yazamıyor (sistem imzası gerekli) P ve 0 km/sa: kapı açılınca dört camı kapat Kapat + Olay kaydı Fatih\'sMG4 ABRP Upload Service Araç + Pencereler Wi-Fi Log