Files
goclaw/ui/web/index.html
T
viettranx b1f6eadf85 feat(channels): TTS auto-apply for Discord/Telegram/WhatsApp + UI enhancements
Backend:
- Add TTS auto-apply support to Discord, Telegram, WhatsApp channels
- Improve text processing for TTS strip markdown
- Wire TTS config handler to gateway server

UI:
- Add voice recorder hook for chat input
- Add agent hooks tab with summary card
- Update i18n for agents (en/vi/zh)
- Minor CSP and credential section fixes
2026-04-16 21:30:10 +07:00

56 lines
3.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<!--
Content-Security-Policy (Phase 06):
- default-src 'self' — deny everything by default.
- script-src 'self' — no 'unsafe-eval'; Prism uses static highlighting only
so the script editor stays XSS-safe even when users paste malicious JS
source (it is rendered as text, never executed in-page).
- style-src 'self' 'unsafe-inline' — Tailwind/inline loader keyframes +
Google Fonts stylesheet require inline styles.
- font-src self + gstatic — Google Fonts woff2 files.
- img-src self + data: + blob: — base64 avatars/thumbnails, blob previews.
- media-src self + blob: — TTS audio playback via blob URLs.
- connect-src self + ws:/wss: — websocket to gateway. Same-origin only;
if the gateway is hosted on a different domain in production, add the
explicit origin here rather than wildcard-allowing all http(s):.
-->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net; font-src 'self' data: https://fonts.gstatic.com https://cdn.jsdelivr.net; img-src 'self' data: blob:; media-src 'self' blob:; connect-src 'self' ws: wss:; base-uri 'self';" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css" crossorigin="anonymous" />
<title>GoClaw Dashboard</title>
<style>
#app-loader{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;background:#fff}
.loader-content{display:flex;flex-direction:column;align-items:center}
.loader-logo{width:4rem;height:4rem;animation:pulse 1.5s ease-in-out infinite}
.loader-shimmer{width:10rem;height:3px;margin-top:1rem;overflow:hidden;border-radius:9999px;background:#e4e4e7}
.shimmer-bar{height:100%;width:33%;border-radius:9999px;background:linear-gradient(90deg,transparent,#a1a1aa,transparent);animation:shimmer 1.2s linear infinite}
@keyframes pulse{0%,100%{opacity:.5;transform:scale(.92)}50%{opacity:1;transform:scale(1)}}
@keyframes shimmer{from{transform:translateX(-10rem)}to{transform:translateX(10rem)}}
.fade-out{opacity:0;transition:opacity 300ms ease}
@media(prefers-reduced-motion:reduce){.loader-logo{animation:none;opacity:1}.shimmer-bar{animation:none}}
@media(prefers-color-scheme:dark){
#app-loader{background:#09090b}
.loader-shimmer{background:#27272a}
.shimmer-bar{background:linear-gradient(90deg,transparent,#52525b,transparent)}
}
</style>
</head>
<body>
<div id="app-loader">
<div class="loader-content">
<img src="/goclaw-icon.svg" alt="GoClaw" class="loader-logo" />
<div class="loader-shimmer"><div class="shimmer-bar"></div></div>
</div>
</div>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>