Implement HTTPS redirection for certificate trust issues in LuxsinAPI and update image paths in Home component to use BASE_URL for consistency.
This commit is contained in:
@@ -188,11 +188,28 @@ export class LuxsinAPI {
|
||||
this.baseUrl = `${protocol}://${host}`;
|
||||
}
|
||||
|
||||
private maybeRedirectForHttpsCert(error: unknown) {
|
||||
// On HTTPS pages, first-time device access may fail before user trusts the cert.
|
||||
if (typeof window === "undefined") return;
|
||||
if (window.location.protocol !== "https:") return;
|
||||
if (!(error instanceof Error)) return;
|
||||
// fetch network failure is typically reported as TypeError/Failed to fetch.
|
||||
const msg = (error.message || "").toLowerCase();
|
||||
if (error.name === "TypeError" || msg.includes("failed to fetch") || msg.includes("networkerror")) {
|
||||
window.location.href = this.baseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
async getDeviceState(): Promise<DeviceState> {
|
||||
const response = await fetch(`${this.baseUrl}/dev/info.cgi?action=syncData`);
|
||||
const text = await response.text();
|
||||
const decoded = decodeCustomBase64(text.trim());
|
||||
return JSON.parse(decoded) as DeviceState;
|
||||
try {
|
||||
const response = await fetch(`${this.baseUrl}/dev/info.cgi?action=syncData`);
|
||||
const text = await response.text();
|
||||
const decoded = decodeCustomBase64(text.trim());
|
||||
return JSON.parse(decoded) as DeviceState;
|
||||
} catch (error) {
|
||||
this.maybeRedirectForHttpsCert(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getMsgCount(): Promise<number> {
|
||||
|
||||
@@ -395,14 +395,16 @@ export default function Home() {
|
||||
onClick={() => updateSetting({ bt_next: 0 })}
|
||||
className="w-10 h-10 rounded-full flex items-center justify-center transition-all active:scale-95"
|
||||
style={{ background: "rgba(0,255,246,0.15)", border: "1px solid rgba(0,255,246,0.3)" }}>
|
||||
<img src="/player/skip-forward.png" alt="上一首" className="w-5 h-5" />
|
||||
<img src={`${import.meta.env.BASE_URL}player/skip-forward.png`} alt="上一首" className="w-5 h-5" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => updateSetting({ bt_play: 1 })}
|
||||
className="w-12 h-12 rounded-full flex items-center justify-center transition-all active:scale-95"
|
||||
style={{ background: "transparent", border: "1px solid rgba(0,255,246,0.5)", boxShadow: "0 0 12px rgba(0,255,246,0.4)" }}>
|
||||
<img
|
||||
src={ds.bt_status === 1 ? "/player/play.png" : "/player/pause.png"}
|
||||
src={ds.bt_status === 1
|
||||
? `${import.meta.env.BASE_URL}player/play.png`
|
||||
: `${import.meta.env.BASE_URL}player/pause.png`}
|
||||
alt={ds.bt_status === 1 ? "播放" : "暂停"}
|
||||
className="w-6 h-6"
|
||||
/>
|
||||
@@ -411,7 +413,7 @@ export default function Home() {
|
||||
onClick={() => updateSetting({ bt_next: 1 })}
|
||||
className="w-10 h-10 rounded-full flex items-center justify-center transition-all active:scale-95"
|
||||
style={{ background: "rgba(0,255,246,0.15)", border: "1px solid rgba(0,255,246,0.3)" }}>
|
||||
<img src="/player/skip-back.png" alt="下一首" className="w-5 h-5" />
|
||||
<img src={`${import.meta.env.BASE_URL}player/skip-back.png`} alt="下一首" className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user