fix(client): show embedded digital employee directly
This commit is contained in:
@@ -8,6 +8,12 @@
|
|||||||
<title>sgRobot</title>
|
<title>sgRobot</title>
|
||||||
<script>
|
<script>
|
||||||
window.__TAURI__ = window.__TAURI__ || {};
|
window.__TAURI__ = window.__TAURI__ || {};
|
||||||
|
try {
|
||||||
|
window.localStorage.setItem("zeroclaw_token", "qimingclaw_embedded_digital_employee");
|
||||||
|
window.sessionStorage.setItem("sgrobot_logged_in", "1");
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("[qimingclaw] digital employee auth bootstrap skipped", error);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/sgrobot-digital/assets/index-DwDxQhF4.js"></script>
|
<script type="module" crossorigin src="/sgrobot-digital/assets/index-DwDxQhF4.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/sgrobot-digital/assets/index-BTJFqpbJ.css">
|
<link rel="stylesheet" crossorigin href="/sgrobot-digital/assets/index-BTJFqpbJ.css">
|
||||||
|
|||||||
@@ -1,39 +1,18 @@
|
|||||||
import React, {
|
import React, {
|
||||||
useCallback,
|
|
||||||
useEffect,
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Alert, Button, Input, message } from "antd";
|
import { Alert } from "antd";
|
||||||
import { ReloadOutlined, SaveOutlined } from "@ant-design/icons";
|
|
||||||
import { APP_DISPLAY_NAME } from "@shared/constants";
|
import { APP_DISPLAY_NAME } from "@shared/constants";
|
||||||
import { t } from "../../services/core/i18n";
|
import { t } from "../../services/core/i18n";
|
||||||
import styles from "../../styles/components/OverviewPage.module.css";
|
import styles from "../../styles/components/OverviewPage.module.css";
|
||||||
|
|
||||||
const OVERVIEW_URL_SETTING_KEY = "overview.digital_employee_url";
|
|
||||||
const DEFAULT_OVERVIEW_URL = "sgrobot-digital/index.html#/digital";
|
const DEFAULT_OVERVIEW_URL = "sgrobot-digital/index.html#/digital";
|
||||||
|
|
||||||
function normalizeOverviewUrl(value: string): string {
|
|
||||||
const trimmed = value.trim();
|
|
||||||
if (!trimmed) return DEFAULT_OVERVIEW_URL;
|
|
||||||
const url = new URL(trimmed, window.location.href);
|
|
||||||
const legacySgRobotEndpoint =
|
|
||||||
(url.hostname === "localhost" && url.port === "5173") ||
|
|
||||||
(url.hostname === "127.0.0.1" && url.port === "42617");
|
|
||||||
if (legacySgRobotEndpoint && url.pathname === "/_app/digital") {
|
|
||||||
return DEFAULT_OVERVIEW_URL;
|
|
||||||
}
|
|
||||||
if (!["http:", "https:", "file:"].includes(url.protocol)) {
|
|
||||||
throw new Error("Unsupported protocol");
|
|
||||||
}
|
|
||||||
return trimmed;
|
|
||||||
}
|
|
||||||
|
|
||||||
function OverviewPage() {
|
function OverviewPage() {
|
||||||
const webviewRef = useRef<HTMLElement | null>(null);
|
const webviewRef = useRef<HTMLElement | null>(null);
|
||||||
const [url, setUrl] = useState(DEFAULT_OVERVIEW_URL);
|
|
||||||
const [draftUrl, setDraftUrl] = useState(DEFAULT_OVERVIEW_URL);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [userAgent, setUserAgent] = useState<string | undefined>();
|
const [userAgent, setUserAgent] = useState<string | undefined>();
|
||||||
|
|
||||||
@@ -46,22 +25,6 @@ function OverviewPage() {
|
|||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let mounted = true;
|
|
||||||
window.electronAPI?.settings
|
|
||||||
.get(OVERVIEW_URL_SETTING_KEY)
|
|
||||||
.then((saved) => {
|
|
||||||
if (!mounted || typeof saved !== "string" || !saved.trim()) return;
|
|
||||||
const normalized = normalizeOverviewUrl(saved);
|
|
||||||
setUrl(normalized);
|
|
||||||
setDraftUrl(normalized);
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
return () => {
|
|
||||||
mounted = false;
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const el = webviewRef.current as any;
|
const el = webviewRef.current as any;
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
@@ -85,58 +48,15 @@ function OverviewPage() {
|
|||||||
el.removeEventListener("did-start-loading", handleStartLoading);
|
el.removeEventListener("did-start-loading", handleStartLoading);
|
||||||
el.removeEventListener("did-fail-load", handleFailLoad);
|
el.removeEventListener("did-fail-load", handleFailLoad);
|
||||||
};
|
};
|
||||||
}, [url]);
|
|
||||||
|
|
||||||
const canSave = useMemo(() => draftUrl.trim() !== url, [draftUrl, url]);
|
|
||||||
const webviewUrl = useMemo(
|
|
||||||
() => new URL(url, window.location.href).toString(),
|
|
||||||
[url],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleReload = useCallback(() => {
|
|
||||||
setError(null);
|
|
||||||
(webviewRef.current as any)?.reload?.();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSave = useCallback(async () => {
|
const webviewUrl = useMemo(
|
||||||
try {
|
() => new URL(DEFAULT_OVERVIEW_URL, window.location.href).toString(),
|
||||||
const normalized = normalizeOverviewUrl(draftUrl);
|
[],
|
||||||
await window.electronAPI?.settings.set(
|
|
||||||
OVERVIEW_URL_SETTING_KEY,
|
|
||||||
normalized,
|
|
||||||
);
|
);
|
||||||
setUrl(normalized);
|
|
||||||
setDraftUrl(normalized);
|
|
||||||
setError(null);
|
|
||||||
message.success(t("Claw.Overview.urlSaved"));
|
|
||||||
} catch {
|
|
||||||
message.error(t("Claw.Overview.invalidUrl"));
|
|
||||||
}
|
|
||||||
}, [draftUrl]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<div className={styles.toolbar}>
|
|
||||||
<span className={styles.title}>{t("Claw.Overview.title")}</span>
|
|
||||||
<Input
|
|
||||||
size="small"
|
|
||||||
className={styles.urlInput}
|
|
||||||
value={draftUrl}
|
|
||||||
onChange={(e) => setDraftUrl(e.target.value)}
|
|
||||||
onPressEnter={handleSave}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
size="small"
|
|
||||||
icon={<SaveOutlined />}
|
|
||||||
onClick={handleSave}
|
|
||||||
disabled={!canSave}
|
|
||||||
>
|
|
||||||
{t("Claw.Common.save")}
|
|
||||||
</Button>
|
|
||||||
<Button size="small" icon={<ReloadOutlined />} onClick={handleReload}>
|
|
||||||
{t("Claw.Common.refresh")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{error && (
|
{error && (
|
||||||
<Alert
|
<Alert
|
||||||
message={error}
|
message={error}
|
||||||
|
|||||||
@@ -7,28 +7,6 @@
|
|||||||
background: var(--color-bg-layout);
|
background: var(--color-bg-layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 8px 12px;
|
|
||||||
border-bottom: 1px solid var(--color-border);
|
|
||||||
background: var(--color-bg-container);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
.urlInput {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 180px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
margin: 8px 12px 0;
|
margin: 8px 12px 0;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user