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:
yangy
2026-04-21 15:29:29 +08:00
parent cf970a6a7f
commit 060258ea2d
6 changed files with 38 additions and 7 deletions
+4 -2
View File
@@ -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 () => {
+4 -3
View File
@@ -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();
+14 -1
View File
@@ -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> {
+1 -1
View File
@@ -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() {