Spaces:
Sleeping
Sleeping
Download dashboard/studio.html from JuanCS-Dev/twitch-byte-bot: direct link, hf CLI and curl.
- Browser
- Download file 12.3 kB
-
https://huggingface.co/spaces/JuanCS-Dev/twitch-byte-bot/resolve/main/dashboard/studio.html
- Command line
-
hf download hf://spaces/JuanCS-Dev/twitch-byte-bot/dashboard/studio.html
-
curl -L -o studio.html https://huggingface.co/spaces/JuanCS-Dev/twitch-byte-bot/resolve/main/dashboard/studio.html
12.3 kB
| <html lang="pt-BR"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <meta name="theme-color" content="#fff4ec" /> | |
| <title>Byte Studio · Painel do Streamer</title> | |
| <link rel="manifest" href="/studio.webmanifest" /> | |
| <link rel="apple-touch-icon" href="/dashboard/icon-192.png" /> | |
| <link rel="stylesheet" href="/dashboard/styles/studio.css" /> | |
| <link rel="stylesheet" href="/dashboard/styles/tokens-studio.css" /> | |
| <link rel="stylesheet" href="/dashboard/styles/mascot.css" /> | |
| </head> | |
| <body class="studio"> | |
| <div class="studio-shell"> | |
| <!-- Brand --> | |
| <div class="studio-brand"> | |
| <div id="mahAvatar" class="mah-avatar studio-mah is-unseen" title="Mah"></div> | |
| <div id="byteMascot" class="byte-mascot studio-byte" title="Byte"></div> | |
| <span class="brand-mark">BYTE</span> | |
| <span class="brand-tag">STUDIO</span> | |
| <button id="customizeBtn" class="theme-toggle" type="button" aria-label="Customizar painel"> | |
| layout | |
| </button> | |
| <button id="themeToggle" class="theme-toggle" type="button" aria-label="Trocar tema"> | |
| tema: auto | |
| </button> | |
| </div> | |
| <!-- Status (orb halo + health chip = one-glance operational truth) --> | |
| <header id="studioStatus" class="studio-status"> | |
| <span id="statusOrb" class="status-orb"></span> | |
| <div class="status-main"> | |
| <h1 id="statusTitle" class="status-title">Conectando…</h1> | |
| <p id="statusSub" class="status-sub">carregando estado do Byte</p> | |
| </div> | |
| <div class="status-right"> | |
| <span id="healthChip" class="health-chip">—</span> | |
| <div class="status-uptime"> | |
| <span>uptime</span> | |
| <strong id="statusUptime">—</strong> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Byte copilot hint (optional, dismissible) --> | |
| <div id="byteHint" class="byte-hint is-hidden" role="status"> | |
| <span class="byte-hint-icon" data-icon="zap"></span> | |
| <span id="byteHintText" class="byte-hint-text"></span> | |
| <button id="byteHintClose" class="byte-hint-close" type="button" aria-label="Dispensar">×</button> | |
| </div> | |
| <!-- Chat mood --> | |
| <section class="studio-mood" aria-label="Humor do chat"> | |
| <div class="mood-row"> | |
| <span id="moodFace" class="mood-face" data-icon="faceNeutral"></span> | |
| <div class="mood-text"> | |
| <span id="moodLabel" class="mood-label">lendo o chat</span> | |
| <span class="mood-caption">humor do chat</span> | |
| </div> | |
| <span id="moodScore" class="mood-score">—</span> | |
| </div> | |
| <div class="mood-track"> | |
| <div id="moodFill" class="mood-fill" style="width: 0%"></div> | |
| </div> | |
| </section> | |
| <!-- Vitals: live trends (sparklines) --> | |
| <section class="studio-vitals" aria-label="Tendências"> | |
| <div class="vital"> | |
| <div class="vital-head"><span class="vital-label">humor</span><span id="vitalMoodVal" class="vital-val">—</span></div> | |
| <svg class="vital-spark" viewBox="0 0 100 24" preserveAspectRatio="none" aria-hidden="true"><path id="sparkMood" class="spark-path" d="" /></svg> | |
| </div> | |
| <div class="vital"> | |
| <div class="vital-head"><span class="vital-label">atividade</span><span id="vitalActVal" class="vital-val">—</span></div> | |
| <svg class="vital-spark" viewBox="0 0 100 24" preserveAspectRatio="none" aria-hidden="true"><path id="sparkActivity" class="spark-path" d="" /></svg> | |
| </div> | |
| <div class="vital"> | |
| <div class="vital-head"><span class="vital-label">saúde</span><span id="vitalHealthVal" class="vital-val">—</span></div> | |
| <svg class="vital-spark" viewBox="0 0 100 24" preserveAspectRatio="none" aria-hidden="true"><path id="sparkHealth" class="spark-path" d="" /></svg> | |
| </div> | |
| </section> | |
| <!-- Retention coach (shows when churn risk rises) --> | |
| <section id="retentionBanner" class="retention is-hidden" aria-label="Risco de retenção"> | |
| <div class="retention-head"> | |
| <span id="retentionBand" class="retention-band">—</span> | |
| <span id="retentionTitle" class="retention-title"></span> | |
| </div> | |
| <p id="retentionTactic" class="retention-tactic"></p> | |
| </section> | |
| <!-- Tiles --> | |
| <section id="studioGrid" class="studio-grid" aria-label="Controles"> | |
| <button id="tilePause" class="tile tile-primary" type="button"> | |
| <span class="tile-ico" data-icon="pause"></span> | |
| <span class="tile-label">PAUSAR</span> | |
| <span class="tile-sub">Byte ativo agora</span> | |
| </button> | |
| <button id="tileSpeak" class="tile" type="button"> | |
| <span class="tile-ico" data-icon="message"></span> | |
| <span class="tile-label">FALAR</span> | |
| <span class="tile-sub">mande o Byte dizer algo</span> | |
| </button> | |
| <button id="tileHype" class="tile tile-live" type="button"> | |
| <span class="tile-ico" data-icon="zap"></span> | |
| <span class="tile-label">HYPE</span> | |
| <span class="tile-sub">solta energia no chat</span> | |
| </button> | |
| <button id="tileApprove" class="tile" type="button" disabled> | |
| <span id="approveBadge" class="tile-badge is-hidden">0</span> | |
| <span class="tile-ico" data-icon="check"></span> | |
| <span class="tile-label">APROVAR</span> | |
| <span class="tile-sub">nada pendente</span> | |
| </button> | |
| <button id="tileVision" class="tile" type="button"> | |
| <span class="tile-ico" data-icon="eye"></span> | |
| <span class="tile-label">VISÃO</span> | |
| <span class="tile-sub">—</span> | |
| </button> | |
| <button id="tileClips" class="tile" type="button"> | |
| <span class="tile-ico" data-icon="scissors"></span> | |
| <span class="tile-label">CLIPES</span> | |
| <span class="tile-sub">—</span> | |
| </button> | |
| <button id="tileChannels" class="tile" type="button"> | |
| <span class="tile-ico" data-icon="broadcast"></span> | |
| <span class="tile-label">CANAIS</span> | |
| <span class="tile-sub">entrar / sair</span> | |
| </button> | |
| <button id="tileAct" class="tile tile-primary" type="button"> | |
| <span class="tile-ico" data-icon="target"></span> | |
| <span class="tile-label">AGIR</span> | |
| <span class="tile-sub">Byte toma atitude agora</span> | |
| </button> | |
| <button id="tileRecap" class="tile" type="button"> | |
| <span class="tile-ico" data-icon="chart"></span> | |
| <span class="tile-label">RECAP</span> | |
| <span class="tile-sub">resumo da live</span> | |
| </button> | |
| </section> | |
| <!-- Live ticker --> | |
| <section class="studio-ticker" aria-label="Atividade ao vivo"> | |
| <div class="ticker-head"> | |
| <span class="ticker-pulse" data-icon="pulse"></span> | |
| O que o Byte está fazendo | |
| </div> | |
| <ul id="tickerList" class="ticker-list"> | |
| <li class="ticker-empty">Carregando atividade…</li> | |
| </ul> | |
| </section> | |
| <p class="studio-foot"> | |
| Modo simples para streamers · | |
| <a href="/">abrir painel ops avançado →</a> | |
| </p> | |
| </div> | |
| <!-- Toast --> | |
| <div id="studioToast" class="studio-toast" role="status" aria-live="polite"></div> | |
| <!-- Command palette (Cmd/Ctrl+K) --> | |
| <div id="commandPalette" class="cmd-palette" role="dialog" aria-modal="true" aria-label="Paleta de comandos"> | |
| <div class="cmd-box"> | |
| <input | |
| id="cmdInput" | |
| class="cmd-input" | |
| type="text" | |
| autocomplete="off" | |
| placeholder="Buscar ação… (atalhos: P F H A V C G R T)" | |
| aria-label="Buscar comando" | |
| /> | |
| <ul id="cmdList" class="cmd-list" role="listbox"></ul> | |
| </div> | |
| </div> | |
| <!-- Speak modal --> | |
| <div id="speakModal" class="studio-modal" role="dialog" aria-modal="true"> | |
| <div class="modal-card"> | |
| <h2>O que o Byte deve dizer?</h2> | |
| <textarea | |
| id="speakInput" | |
| placeholder="Ex: Bem-vindos, galera! Curtam a live." | |
| ></textarea> | |
| <div class="modal-actions"> | |
| <button id="speakCancel" class="btn-cancel" type="button"> | |
| Cancelar | |
| </button> | |
| <button id="speakSend" class="btn-send" type="button">Enviar</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Channels modal --> | |
| <div id="channelsModal" class="studio-modal" role="dialog" aria-modal="true"> | |
| <div class="modal-card"> | |
| <h2>Conexão de canais</h2> | |
| <p id="channelsStatus" class="modal-hint">Carregando canais…</p> | |
| <input | |
| id="channelInput" | |
| type="text" | |
| autocomplete="off" | |
| placeholder="login do canal (sem @)" | |
| /> | |
| <div class="modal-actions"> | |
| <button id="channelPart" class="btn-cancel" type="button">Sair</button> | |
| <button id="channelJoin" class="btn-send" type="button">Entrar</button> | |
| </div> | |
| <button id="channelsClose" class="btn-ghost" type="button">Fechar</button> | |
| </div> | |
| </div> | |
| <!-- Approvals modal --> | |
| <div id="approveModal" class="studio-modal" role="dialog" aria-modal="true"> | |
| <div class="modal-card"> | |
| <h2>Ações aguardando aprovação</h2> | |
| <div id="approveList" class="approve-list">Carregando…</div> | |
| <div class="modal-actions"> | |
| <button id="approveClose" class="btn-send" type="button">Fechar</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Recap modal --> | |
| <div id="recapModal" class="studio-modal" role="dialog" aria-modal="true"> | |
| <div class="modal-card"> | |
| <h2>Resumo da live</h2> | |
| <div id="recapBody" class="recap-body">Gerando…</div> | |
| <div class="modal-actions"> | |
| <button id="recapClose" class="btn-send" type="button">Fechar</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Layout customization --> | |
| <div id="layoutModal" class="studio-modal" role="dialog" aria-modal="true"> | |
| <div class="modal-card"> | |
| <h2>Customizar painel</h2> | |
| <div class="layout-section"> | |
| <span class="layout-sub">Perfil</span> | |
| <div class="layout-row"> | |
| <button class="layout-chip" data-profile="full" type="button">Completo</button> | |
| <button class="layout-chip" data-profile="fps" type="button">FPS</button> | |
| <button class="layout-chip" data-profile="chatting" type="button">Just Chatting</button> | |
| </div> | |
| </div> | |
| <div class="layout-section"> | |
| <span class="layout-sub">Densidade</span> | |
| <div class="layout-row"> | |
| <button class="layout-chip" data-density="comfortable" type="button">Confortável</button> | |
| <button class="layout-chip" data-density="compact" type="button">Compacto</button> | |
| </div> | |
| </div> | |
| <div class="layout-section"> | |
| <span class="layout-sub">Tiles (mostrar / reordenar)</span> | |
| <ul id="layoutTiles" class="layout-tiles"></ul> | |
| </div> | |
| <div class="modal-actions"> | |
| <button id="layoutReset" class="btn-cancel" type="button">Resetar</button> | |
| <button id="layoutClose" class="btn-send" type="button">Fechar</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Token gate --> | |
| <div id="studioGate" class="studio-gate" role="dialog" aria-modal="true"> | |
| <div class="gate-card"> | |
| <span class="gate-ico" data-icon="key"></span> | |
| <h2>Quase lá</h2> | |
| <p>Cole seu token de acesso para liberar o painel.</p> | |
| <input | |
| id="gateInput" | |
| type="password" | |
| autocomplete="off" | |
| placeholder="Token de admin" | |
| /> | |
| <button id="gateSave" type="button">Entrar</button> | |
| <ol class="gate-steps"> | |
| <li><b>1.</b> Cole o token de admin acima</li> | |
| <li><b>2.</b> Conecte seu canal no tile <b>CANAIS</b></li> | |
| <li><b>3.</b> No OBS, adicione <code>/voice</code> e <code>/avatar</code></li> | |
| </ol> | |
| </div> | |
| </div> | |
| <script type="module" src="/dashboard/features/studio/main.js"></script> | |
| </body> | |
| </html> | |