mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-10 18:23:44 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c35e376e9 |
@@ -1,15 +1,35 @@
|
|||||||
import { BluetoothPanel } from "../components/BluetoothPanel.js"
|
import { BluetoothPanel } from "../components/BluetoothPanel.js"
|
||||||
|
import { WheelControls } from "../components/WheelControls.js"
|
||||||
import { GalaxySection } from "../components/GalaxySection.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 = {
|
export const Bluetooth = {
|
||||||
name: "Bluetooth",
|
name: "Bluetooth",
|
||||||
components: { BluetoothPanel, GalaxySection },
|
components: { BluetoothPanel, WheelControls, GalaxySection, GalaxyTabs },
|
||||||
|
setup() {
|
||||||
|
return useTabRouting("/bluetooth", { bluetooth: "bluetooth", controllers: "controllers" })
|
||||||
|
},
|
||||||
|
data() { return { TABS } },
|
||||||
template: `
|
template: `
|
||||||
<div class="gx-view">
|
<div class="gx-view">
|
||||||
<h2 style="margin-top:0;">Bluetooth</h2>
|
<h2 style="margin-top:0;">Bluetooth</h2>
|
||||||
|
<GalaxyTabs :items="TABS" :active="tab" @select="selectTab" />
|
||||||
|
|
||||||
|
<template v-if="tab === 'bluetooth'">
|
||||||
<GalaxySection title="Bluetooth Devices" icon="bi-bluetooth" :collapsible="false">
|
<GalaxySection title="Bluetooth Devices" icon="bi-bluetooth" :collapsible="false">
|
||||||
<BluetoothPanel />
|
<BluetoothPanel />
|
||||||
</GalaxySection>
|
</GalaxySection>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
<WheelControls />
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import { PwaInstallSection, isFirestarOrigin } from "../components/PwaInstallSec
|
|||||||
|
|
||||||
const isTunnel = () => isFirestarOrigin()
|
const isTunnel = () => isFirestarOrigin()
|
||||||
|
|
||||||
function localDeviceUrl(ip) {
|
function localDeviceUrl(ip, route = "/") {
|
||||||
const raw = String(ip || "").trim()
|
const raw = String(ip || "").trim()
|
||||||
if (!raw || raw === "unknown") return ""
|
if (!raw || raw === "unknown") return ""
|
||||||
const host = raw.includes(":") && !raw.startsWith("[") ? `[${raw}]` : raw
|
const host = raw.includes(":") && !raw.startsWith("[") ? `[${raw}]` : raw
|
||||||
return `http://${host}:8082`
|
return `http://${host}:8082/#${route}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Galaxy = {
|
export const Galaxy = {
|
||||||
@@ -28,7 +28,7 @@ export const Galaxy = {
|
|||||||
if (this.isTunnel) {
|
if (this.isTunnel) {
|
||||||
try {
|
try {
|
||||||
const status = await api.getDeviceStatus()
|
const status = await api.getDeviceStatus()
|
||||||
this.localUrl = localDeviceUrl(status?.lanIp)
|
this.localUrl = localDeviceUrl(status?.lanIp, "/galaxy")
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,10 @@ export const Galaxy = {
|
|||||||
<strong>Galaxy Pairing Unavailable via Galaxy</strong>
|
<strong>Galaxy Pairing Unavailable via Galaxy</strong>
|
||||||
<span>
|
<span>
|
||||||
Galaxy pairing requires a direct connection. If you are on the same local network, connect here:
|
Galaxy pairing requires a direct connection. If you are on the same local network, connect here:
|
||||||
<a v-if="localUrl" :href="localUrl" style="color:inherit; font-weight:var(--fw-bold); overflow-wrap:anywhere;">{{ localUrl }}</a>
|
<br />
|
||||||
|
<a v-if="localUrl" class="gx-btn gx-btn--tonal" :href="localUrl" style="margin-top:var(--sp-3);">
|
||||||
|
<i class="bi bi-box-arrow-up-right"></i> Open Galaxy Locally
|
||||||
|
</a>
|
||||||
<span v-else>your device's local IP on port 8082.</span>
|
<span v-else>your device's local IP on port 8082.</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -52,11 +52,11 @@ function normalizeRoute(r) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function localDeviceUrl(ip) {
|
function localDeviceUrl(ip, route = "/") {
|
||||||
const raw = String(ip || "").trim()
|
const raw = String(ip || "").trim()
|
||||||
if (!raw || raw === "unknown") return ""
|
if (!raw || raw === "unknown") return ""
|
||||||
const host = raw.includes(":") && !raw.startsWith("[") ? `[${raw}]` : raw
|
const host = raw.includes(":") && !raw.startsWith("[") ? `[${raw}]` : raw
|
||||||
return `http://${host}:8082`
|
return `http://${host}:8082/#${route}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Recordings = {
|
export const Recordings = {
|
||||||
@@ -346,7 +346,7 @@ export const Recordings = {
|
|||||||
if (this.onFirestar) {
|
if (this.onFirestar) {
|
||||||
try {
|
try {
|
||||||
const status = await api.getDeviceStatus()
|
const status = await api.getDeviceStatus()
|
||||||
this.localUrl = localDeviceUrl(status?.lanIp)
|
this.localUrl = localDeviceUrl(status?.lanIp, "/recordings")
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -520,7 +520,10 @@ export const Recordings = {
|
|||||||
|
|
||||||
<GxNotice v-else tone="info" icon="bi-satellite" title="Recordings unavailable via Galaxy">
|
<GxNotice v-else tone="info" icon="bi-satellite" title="Recordings unavailable via Galaxy">
|
||||||
Recordings are unavailable via Galaxy for bandwidth reasons. If you are on the same local network, connect here:
|
Recordings are unavailable via Galaxy for bandwidth reasons. If you are on the same local network, connect here:
|
||||||
<a v-if="localUrl" :href="localUrl" style="color:inherit; font-weight:var(--fw-bold); overflow-wrap:anywhere;">{{ localUrl }}</a>
|
<br />
|
||||||
|
<a v-if="localUrl" class="gx-btn gx-btn--tonal" :href="localUrl" style="margin-top:var(--sp-3);">
|
||||||
|
<i class="bi bi-box-arrow-up-right"></i> Open Recordings Locally
|
||||||
|
</a>
|
||||||
<span v-else>your device's local IP on port 8082.</span>
|
<span v-else>your device's local IP on port 8082.</span>
|
||||||
</GxNotice>
|
</GxNotice>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const TOOLS = [
|
|||||||
{ name: "System Tools", link: "/system", icon: "bi-arrow-repeat", desc: "Backup, restore, updates" },
|
{ 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: "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: "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))
|
].sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
|
||||||
export const Tools = {
|
export const Tools = {
|
||||||
|
|||||||
@@ -1,34 +1,22 @@
|
|||||||
import { api, showSnackbar } from "../api.js"
|
import { api, showSnackbar } from "../api.js"
|
||||||
import { navigate, toolHref } from "../store.js"
|
import { navigate, toolHref } from "../store.js"
|
||||||
import { WheelControls } from "../components/WheelControls.js"
|
|
||||||
import { GalaxySection } from "../components/GalaxySection.js"
|
import { GalaxySection } from "../components/GalaxySection.js"
|
||||||
import { GalaxyTabs } from "../components/GalaxyTabs.js"
|
|
||||||
import { useTabRouting } from "../composables.js"
|
|
||||||
|
|
||||||
const FEATURES = [
|
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: "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" },
|
{ 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 = {
|
export const Vehicle = {
|
||||||
name: "Vehicle",
|
name: "Vehicle",
|
||||||
components: { WheelControls, GalaxySection, GalaxyTabs },
|
components: { GalaxySection },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
TABS,
|
|
||||||
features: FEATURES,
|
features: FEATURES,
|
||||||
featureStatus: {},
|
featureStatus: {},
|
||||||
busy: "",
|
busy: "",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup() {
|
|
||||||
return useTabRouting("/vehicle", { controllers: "controllers", features: "features" })
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
featureList() { return this.features },
|
featureList() { return this.features },
|
||||||
},
|
},
|
||||||
@@ -63,13 +51,6 @@ export const Vehicle = {
|
|||||||
<div class="gx-view">
|
<div class="gx-view">
|
||||||
<h2 style="margin-top:0;">Vehicle Controls</h2>
|
<h2 style="margin-top:0;">Vehicle Controls</h2>
|
||||||
|
|
||||||
<GalaxyTabs :items="TABS" :active="tab" @select="selectTab" />
|
|
||||||
|
|
||||||
<template v-if="tab === 'controllers'">
|
|
||||||
<WheelControls />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-else>
|
|
||||||
<GalaxySection title="Vehicle Features" icon="bi-check2-square">
|
<GalaxySection title="Vehicle Features" icon="bi-check2-square">
|
||||||
<div style="padding: var(--sp-3); display:grid; gap:8px;">
|
<div style="padding: var(--sp-3); display:grid; gap:8px;">
|
||||||
<button v-for="f in featureList" :key="f.key" type="button"
|
<button v-for="f in featureList" :key="f.key" type="button"
|
||||||
@@ -86,7 +67,6 @@ export const Vehicle = {
|
|||||||
<p style="color:var(--text-muted); margin:0;">These features verify vehicle compatibility when launched.</p>
|
<p style="color:var(--text-muted); margin:0;">These features verify vehicle compatibility when launched.</p>
|
||||||
</div>
|
</div>
|
||||||
</GalaxySection>
|
</GalaxySection>
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,8 +126,8 @@ def test_ui_ports_all_tool_views():
|
|||||||
assert ep in src, f"{rel} should use api.{ep}"
|
assert ep in src, f"{rel} should use api.{ep}"
|
||||||
vehicle = _read("js/views/Vehicle.js")
|
vehicle = _read("js/views/Vehicle.js")
|
||||||
bluetooth = _read("js/views/Bluetooth.js")
|
bluetooth = _read("js/views/Bluetooth.js")
|
||||||
assert "WheelControls" in vehicle and "BluetoothPanel" not in vehicle and "carFeaturesCheck" in vehicle
|
assert "WheelControls" not in vehicle and "BluetoothPanel" not in vehicle and "carFeaturesCheck" in vehicle
|
||||||
assert "BluetoothPanel" in bluetooth
|
assert "BluetoothPanel" in bluetooth and "WheelControls" in bluetooth
|
||||||
|
|
||||||
|
|
||||||
def test_ui_routes_ported_views_natively_no_classic_fallback():
|
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 "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
|
assert "LateralTuningPanel" in tuning and "LongitudinalManeuvers" not in tuning
|
||||||
vehicle = _read("js/views/Vehicle.js")
|
vehicle = _read("js/views/Vehicle.js")
|
||||||
|
bluetooth = _read("js/views/Bluetooth.js")
|
||||||
assert "ParamSections" not in vehicle, "Vehicle must not render redundant toggles"
|
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 "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")
|
engine = _read("js/components/ParamSections.js")
|
||||||
assert "SettingTree" in engine
|
assert "SettingTree" in engine
|
||||||
assert "isSettingVisible" 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 "bandwidth reasons" in recordings and "status?.lanIp" in recordings
|
||||||
assert "status?.lanIp" in galaxy
|
assert "status?.lanIp" in galaxy
|
||||||
assert ':href="localUrl"' in recordings and ':href="localUrl"' 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 = _read("js/views/Home.js")
|
||||||
home_css = _read("css/home.css")
|
home_css = _read("css/home.css")
|
||||||
|
|||||||
Reference in New Issue
Block a user