Enhance Vite configuration with custom input for rollup, update ConnectScreen to validate IP input before connection, and modify DeviceContext to support dynamic IP handling in LuxsinAPI. Adjust VUPage to use BASE_URL for image previews.
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1" />
|
||||
<title>Luxsin X8 Controller</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -11,9 +11,11 @@ export default function ConnectScreen() {
|
||||
const [inputIp, setInputIp] = useState(ip);
|
||||
|
||||
const handleConnect = async () => {
|
||||
setIp(inputIp);
|
||||
const targetIp = inputIp.trim();
|
||||
if (!targetIp) return;
|
||||
setIp(targetIp);
|
||||
setDemoMode(false);
|
||||
await connect();
|
||||
await connect(false, targetIp);
|
||||
};
|
||||
|
||||
const handleDemo = async () => {
|
||||
|
||||
@@ -20,7 +20,7 @@ interface DeviceContextType {
|
||||
peqState: PeqState | null;
|
||||
lastUpdated: Date | null;
|
||||
error: string | null;
|
||||
connect: (forceDemo?: boolean) => Promise<void>;
|
||||
connect: (forceDemo?: boolean, connectIp?: string) => Promise<void>;
|
||||
disconnect: () => void;
|
||||
refresh: () => Promise<void>;
|
||||
api: LuxsinAPI | null;
|
||||
@@ -62,8 +62,9 @@ export function DeviceProvider({ children }: { children: React.ReactNode }) {
|
||||
lastMsgCountRef.current = state.msgCount;
|
||||
}, []);
|
||||
|
||||
const connect = useCallback(async (forceDemo?: boolean) => {
|
||||
const connect = useCallback(async (forceDemo?: boolean, connectIp?: string) => {
|
||||
const useDemo = forceDemo !== undefined ? forceDemo : isDemoMode;
|
||||
const targetIp = (connectIp ?? ip).trim();
|
||||
// Demo mode — use mock data immediately, no network call
|
||||
if (useDemo) {
|
||||
setIsConnecting(true);
|
||||
@@ -80,7 +81,7 @@ export function DeviceProvider({ children }: { children: React.ReactNode }) {
|
||||
setIsConnecting(true);
|
||||
setError(null);
|
||||
try {
|
||||
const newApi = new LuxsinAPI(ip);
|
||||
const newApi = new LuxsinAPI(targetIp);
|
||||
// Fetch device info from http://{ip}/dev/info.cgi?action=syncData
|
||||
// The response is encoded with custom base64, needs decoding
|
||||
const state = await newApi.getDeviceState();
|
||||
|
||||
@@ -165,6 +165,17 @@ export const FILTER_TYPE_LABELS = ["Low Pass", "High Pass", "Band Pass", "Notch"
|
||||
export const DAC_ARC_LABELS = ["ARC", "eARC"];
|
||||
export const BT_STATUS_LABELS = ["Disconnected", "Playing", "Paused"];
|
||||
|
||||
function resolveDeviceProtocol(): "http" | "https" {
|
||||
if (typeof window !== "undefined" && window.location.protocol === "https:") {
|
||||
return "https";
|
||||
}
|
||||
return "http";
|
||||
}
|
||||
|
||||
function normalizeDeviceHost(input: string): string {
|
||||
return input.trim().replace(/^https?:\/\//i, "").replace(/\/+$/, "");
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// API Class
|
||||
// ============================================================
|
||||
@@ -172,7 +183,9 @@ export class LuxsinAPI {
|
||||
private baseUrl: string;
|
||||
|
||||
constructor(ip: string) {
|
||||
this.baseUrl = `http://${ip}`;
|
||||
const host = normalizeDeviceHost(ip);
|
||||
const protocol = resolveDeviceProtocol();
|
||||
this.baseUrl = `${protocol}://${host}`;
|
||||
}
|
||||
|
||||
async getDeviceState(): Promise<DeviceState> {
|
||||
|
||||
@@ -19,7 +19,7 @@ interface VUStyle {
|
||||
const VU_STYLES: VUStyle[] = Array.from({ length: 16 }, (_, i) => ({
|
||||
index: i,
|
||||
name: `VU ${i + 1}`,
|
||||
preview: `/vu/vu${i + 1}.png`,
|
||||
preview: `${import.meta.env.BASE_URL}vu/vu${i + 1}.png`,
|
||||
}));
|
||||
|
||||
export default function VUPage() {
|
||||
|
||||
@@ -179,6 +179,9 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
rollupOptions: {
|
||||
input: {
|
||||
i: path.resolve(import.meta.dirname, "client", "i.html"),
|
||||
},
|
||||
output: {
|
||||
manualChunks(id) {
|
||||
if (!id.includes("node_modules")) return;
|
||||
|
||||
Reference in New Issue
Block a user