diff --git a/starpilot/system/the_galaxy/assets/mobile/js/views/Bluetooth.js b/starpilot/system/the_galaxy/assets/mobile/js/views/Bluetooth.js index 23cb61cfa..c3f2ed76a 100644 --- a/starpilot/system/the_galaxy/assets/mobile/js/views/Bluetooth.js +++ b/starpilot/system/the_galaxy/assets/mobile/js/views/Bluetooth.js @@ -1,15 +1,35 @@ import { BluetoothPanel } from "../components/BluetoothPanel.js" +import { WheelControls } from "../components/WheelControls.js" import { GalaxySection } from "../components/GalaxySection.js" +import { GalaxyTabs } from "../components/GalaxyTabs.js" +import { useTabRouting } from "../composables.js" + +const TABS = { + bluetooth: "Bluetooth", + controllers: "Controllers", +} export const Bluetooth = { name: "Bluetooth", - components: { BluetoothPanel, GalaxySection }, + components: { BluetoothPanel, WheelControls, GalaxySection, GalaxyTabs }, + setup() { + return useTabRouting("/bluetooth", { bluetooth: "bluetooth", controllers: "controllers" }) + }, + data() { return { TABS } }, template: `

Bluetooth

- - - + + + + +
`, } diff --git a/starpilot/system/the_galaxy/assets/mobile/js/views/Galaxy.js b/starpilot/system/the_galaxy/assets/mobile/js/views/Galaxy.js index 0ca6433c5..d4e17f5f6 100644 --- a/starpilot/system/the_galaxy/assets/mobile/js/views/Galaxy.js +++ b/starpilot/system/the_galaxy/assets/mobile/js/views/Galaxy.js @@ -4,11 +4,11 @@ import { PwaInstallSection, isFirestarOrigin } from "../components/PwaInstallSec const isTunnel = () => isFirestarOrigin() -function localDeviceUrl(ip) { +function localDeviceUrl(ip, route = "/") { const raw = String(ip || "").trim() if (!raw || raw === "unknown") return "" const host = raw.includes(":") && !raw.startsWith("[") ? `[${raw}]` : raw - return `http://${host}:8082` + return `http://${host}:8082/#${route}` } export const Galaxy = { @@ -28,7 +28,7 @@ export const Galaxy = { if (this.isTunnel) { try { const status = await api.getDeviceStatus() - this.localUrl = localDeviceUrl(status?.lanIp) + this.localUrl = localDeviceUrl(status?.lanIp, "/galaxy") } catch (e) {} return } @@ -92,7 +92,10 @@ export const Galaxy = { Galaxy Pairing Unavailable via Galaxy Galaxy pairing requires a direct connection. If you are on the same local network, connect here: - {{ localUrl }} +
+ + Open Galaxy Locally + your device's local IP on port 8082.
diff --git a/starpilot/system/the_galaxy/assets/mobile/js/views/Recordings.js b/starpilot/system/the_galaxy/assets/mobile/js/views/Recordings.js index 4d39da5fd..c928dd920 100644 --- a/starpilot/system/the_galaxy/assets/mobile/js/views/Recordings.js +++ b/starpilot/system/the_galaxy/assets/mobile/js/views/Recordings.js @@ -52,11 +52,11 @@ function normalizeRoute(r) { } } -function localDeviceUrl(ip) { +function localDeviceUrl(ip, route = "/") { const raw = String(ip || "").trim() if (!raw || raw === "unknown") return "" const host = raw.includes(":") && !raw.startsWith("[") ? `[${raw}]` : raw - return `http://${host}:8082` + return `http://${host}:8082/#${route}` } export const Recordings = { @@ -346,7 +346,7 @@ export const Recordings = { if (this.onFirestar) { try { const status = await api.getDeviceStatus() - this.localUrl = localDeviceUrl(status?.lanIp) + this.localUrl = localDeviceUrl(status?.lanIp, "/recordings") } catch (e) {} return } @@ -520,7 +520,10 @@ export const Recordings = { Recordings are unavailable via Galaxy for bandwidth reasons. If you are on the same local network, connect here: - {{ localUrl }} +
+ + Open Recordings Locally + your device's local IP on port 8082.
diff --git a/starpilot/system/the_galaxy/assets/mobile/js/views/Tools.js b/starpilot/system/the_galaxy/assets/mobile/js/views/Tools.js index 04eb9db1f..7ea87ac7b 100644 --- a/starpilot/system/the_galaxy/assets/mobile/js/views/Tools.js +++ b/starpilot/system/the_galaxy/assets/mobile/js/views/Tools.js @@ -11,7 +11,7 @@ const TOOLS = [ { name: "System Tools", link: "/system", icon: "bi-arrow-repeat", desc: "Backup, restore, updates" }, { name: "Theme Maker", link: "/theme_maker", icon: "bi-palette-fill", desc: "Customize the look" }, { name: "Tuning, Plots & Testing", link: "/tuning", icon: "bi-sign-turn-right", desc: "Steering & speed tuning, live plots, testing grounds" }, - { name: "Vehicle Controls", link: "/vehicle", icon: "bi-car-front", desc: "Controllers & vehicle features" }, + { name: "Vehicle Controls", link: "/vehicle", icon: "bi-car-front", desc: "Vehicle features" }, ].sort((a, b) => a.name.localeCompare(b.name)) export const Tools = { diff --git a/starpilot/system/the_galaxy/assets/mobile/js/views/Vehicle.js b/starpilot/system/the_galaxy/assets/mobile/js/views/Vehicle.js index a3b6e77cc..daf0b91bb 100644 --- a/starpilot/system/the_galaxy/assets/mobile/js/views/Vehicle.js +++ b/starpilot/system/the_galaxy/assets/mobile/js/views/Vehicle.js @@ -1,34 +1,22 @@ import { api, showSnackbar } from "../api.js" import { navigate, toolHref } from "../store.js" -import { WheelControls } from "../components/WheelControls.js" import { GalaxySection } from "../components/GalaxySection.js" -import { GalaxyTabs } from "../components/GalaxyTabs.js" -import { useTabRouting } from "../composables.js" const FEATURES = [ { key: "doors", name: "Lock/Unlock Doors", icon: "bi-door-closed", desc: "Send lock or unlock commands remotely to your vehicle.", embed: "/manage_doors" }, { key: "tsk", name: "Toyota Security Keys", icon: "bi-key-fill", desc: "Manage and apply security keys for secOC protected devices.", embed: "/manage_tsk" }, ] -const TABS = { - controllers: "Controllers", - features: "Vehicle Features", -} - export const Vehicle = { name: "Vehicle", - components: { WheelControls, GalaxySection, GalaxyTabs }, + components: { GalaxySection }, data() { return { - TABS, features: FEATURES, featureStatus: {}, busy: "", } }, - setup() { - return useTabRouting("/vehicle", { controllers: "controllers", features: "features" }) - }, computed: { featureList() { return this.features }, }, @@ -63,30 +51,22 @@ export const Vehicle = {

Vehicle Controls

- - - - - + +
+ +

These features verify vehicle compatibility when launched.

+
+
`, } diff --git a/starpilot/system/the_galaxy/tests/test_ui_vue_frontend.py b/starpilot/system/the_galaxy/tests/test_ui_vue_frontend.py index ee4214534..7e212a1f8 100644 --- a/starpilot/system/the_galaxy/tests/test_ui_vue_frontend.py +++ b/starpilot/system/the_galaxy/tests/test_ui_vue_frontend.py @@ -126,8 +126,8 @@ def test_ui_ports_all_tool_views(): assert ep in src, f"{rel} should use api.{ep}" vehicle = _read("js/views/Vehicle.js") bluetooth = _read("js/views/Bluetooth.js") - assert "WheelControls" in vehicle and "BluetoothPanel" not in vehicle and "carFeaturesCheck" in vehicle - assert "BluetoothPanel" in bluetooth + assert "WheelControls" not in vehicle and "BluetoothPanel" not in vehicle and "carFeaturesCheck" in vehicle + assert "BluetoothPanel" in bluetooth and "WheelControls" in bluetooth def test_ui_routes_ported_views_natively_no_classic_fallback(): @@ -233,9 +233,13 @@ def test_ui_schema_driven_param_engine_reused(): assert "GalaxyEmbed" not in tuning and 'src="/tuning"' not in tuning, "Tuning must be native, not a classic embed" assert "LateralTuningPanel" in tuning and "LongitudinalManeuvers" not in tuning vehicle = _read("js/views/Vehicle.js") + bluetooth = _read("js/views/Bluetooth.js") assert "ParamSections" not in vehicle, "Vehicle must not render redundant toggles" - assert "WheelControls" in vehicle and "BluetoothPanel" not in vehicle + assert "WheelControls" not in vehicle and "BluetoothPanel" not in vehicle assert "GalaxySection" in vehicle + assert "WheelControls" in bluetooth and "BluetoothPanel" in bluetooth + assert bluetooth.index('bluetooth: "Bluetooth"') < bluetooth.index('controllers: "Controllers"') + assert 'useTabRouting("/bluetooth"' in bluetooth engine = _read("js/components/ParamSections.js") assert "SettingTree" in engine assert "isSettingVisible" in engine @@ -517,6 +521,10 @@ def test_ui_mobile_polish_regressions(): assert "bandwidth reasons" in recordings and "status?.lanIp" in recordings assert "status?.lanIp" in galaxy assert ':href="localUrl"' in recordings and ':href="localUrl"' in galaxy + assert 'localDeviceUrl(status?.lanIp, "/recordings")' in recordings + assert 'localDeviceUrl(status?.lanIp, "/galaxy")' in galaxy + assert "gx-btn gx-btn--tonal" in recordings and "Open Recordings Locally" in recordings + assert "gx-btn gx-btn--tonal" in galaxy and "Open Galaxy Locally" in galaxy home = _read("js/views/Home.js") home_css = _read("css/home.css")