Fix: Restore ai_agent and add Gemini Env support
This commit is contained in:
@@ -8,7 +8,7 @@ from config import get_config
|
|||||||
def get_llm_response(prompt: str, provider: str, cfg: dict) -> str:
|
def get_llm_response(prompt: str, provider: str, cfg: dict) -> str:
|
||||||
"""Invoca o provedor de LLM configurado."""
|
"""Invoca o provedor de LLM configurado."""
|
||||||
if provider == "gemini":
|
if provider == "gemini":
|
||||||
api_key = cfg.get("gemini_api_key")
|
api_key = cfg.get("gemini_api_key") or os.getenv("GEMINI_API_KEY")
|
||||||
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={api_key}"
|
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={api_key}"
|
||||||
payload = {"contents": [{"parts": [{"text": prompt}]}]}
|
payload = {"contents": [{"parts": [{"text": prompt}]}]}
|
||||||
res = requests.post(url, json=payload)
|
res = requests.post(url, json=payload)
|
||||||
|
|||||||
@@ -49,12 +49,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Scrollbar Fix for Firefox */
|
/* Scrollbar Fix for Firefox */
|
||||||
@supports (scrollbar-width: thin) {
|
|
||||||
* {
|
* {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
scrollbar-color: var(--accent) transparent;
|
scrollbar-color: var(--accent) transparent;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0% {
|
0% {
|
||||||
@@ -605,7 +603,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
-webkit-backdrop-filter: blur(20px);
|
|
||||||
backdrop-filter: blur(20px);
|
backdrop-filter: blur(20px);
|
||||||
transition: opacity 0.5s ease, visibility 0.5s;
|
transition: opacity 0.5s ease, visibility 0.5s;
|
||||||
}
|
}
|
||||||
@@ -631,104 +628,31 @@
|
|||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-icon {
|
|
||||||
font-size: 3rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-desc {
|
|
||||||
color: var(--text-muted);
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-input {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
letter-spacing: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-btn {
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#login-error {
|
|
||||||
color: var(--danger);
|
|
||||||
font-size: 0.75rem;
|
|
||||||
margin-top: 1rem;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-icon-sun {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-icon-moon {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="light"] .theme-icon-sun {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="light"] .theme-icon-moon {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-input-area {
|
|
||||||
padding: 0.75rem;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.recording-indicator {
|
|
||||||
display: none;
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
background: red;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: pulse 1s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.insights-icon {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.insights-placeholder small {
|
|
||||||
display: block;
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-bar {
|
|
||||||
width: 0%;
|
|
||||||
transition: width 0.5s ease;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="login-overlay">
|
<div id="login-overlay">
|
||||||
<div class="card login-card">
|
<div class="card login-card">
|
||||||
<div class="login-icon" role="img" aria-label="Cadeado de Segurança">🔒</div>
|
<div style="font-size: 3rem; margin-bottom: 1rem;" role="img" aria-label="Cadeado de Segurança">🔒</div>
|
||||||
<h2>Acesso Restrito</h2>
|
<h2>Acesso Restrito</h2>
|
||||||
<p class="login-desc">Esta VPS está protegida. Insira a senha mestra para gerenciar o Agente.</p>
|
<p style="color:var(--text-muted); margin-bottom:1.5rem; font-size:0.85rem;">Esta VPS está protegida. Insira
|
||||||
|
a senha mestra para gerenciar o Agente.</p>
|
||||||
<input type="password" id="web-pass-input" aria-label="Senha da VPS" autocomplete="current-password"
|
<input type="password" id="web-pass-input" aria-label="Senha da VPS" autocomplete="current-password"
|
||||||
class="form-input login-input" placeholder="Senha da VPS"
|
class="form-input" placeholder="Senha da VPS"
|
||||||
|
style="margin-bottom:1rem; text-align:center; font-size: 1.1rem; letter-spacing: 0.2rem;"
|
||||||
onkeypress="if(event.key==='Enter') attemptLogin()">
|
onkeypress="if(event.key==='Enter') attemptLogin()">
|
||||||
<button type="button" class="btn btn-primary login-btn"
|
<button type="button" class="btn btn-primary" style="width:100%; padding: 0.8rem;"
|
||||||
onclick="attemptLogin()">Entrar no Dashboard</button>
|
onclick="attemptLogin()">Entrar no Dashboard</button>
|
||||||
<div id="login-error">Senha incorreta. Tente novamente.</div>
|
<div id="login-error" style="color:var(--danger); font-size: 0.75rem; margin-top: 1rem; display: none;">
|
||||||
|
Senha incorreta. Tente novamente.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<header>
|
<header>
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
|
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
|
||||||
</svg>
|
</svg>
|
||||||
<h1>VPS AI Dashboard</h1>
|
<h1>VPS AI Dashboard</h1>
|
||||||
@@ -736,12 +660,12 @@
|
|||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<div class="status-badge" id="bot-status">Online</div>
|
<div class="status-badge" id="bot-status">Online</div>
|
||||||
<button type="button" class="theme-toggle" onclick="toggleTheme()" aria-label="Alternar tema">
|
<button type="button" class="theme-toggle" onclick="toggleTheme()" aria-label="Alternar tema">
|
||||||
<svg id="icon-sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="theme-icon-sun">
|
<svg id="icon-sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="display: none;">
|
||||||
<circle cx="12" cy="12" r="5" />
|
<circle cx="12" cy="12" r="5" />
|
||||||
<path
|
<path
|
||||||
d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
|
d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg id="icon-moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="theme-icon-moon">
|
<svg id="icon-moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
|
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
@@ -754,56 +678,57 @@
|
|||||||
<h3>CPU</h3>
|
<h3>CPU</h3>
|
||||||
<div class="stat-value" id="cpu-val">--%</div>
|
<div class="stat-value" id="cpu-val">--%</div>
|
||||||
<div class="progress-bar-bg">
|
<div class="progress-bar-bg">
|
||||||
<div class="progress-bar" id="cpu-bar"></div>
|
<div class="progress-bar" id="cpu-bar" style="width: 0%"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card stat-card">
|
<div class="card stat-card">
|
||||||
<h3>RAM</h3>
|
<h3>RAM</h3>
|
||||||
<div class="stat-value" id="ram-val">-- / -- GB</div>
|
<div class="stat-value" id="ram-val">-- / -- GB</div>
|
||||||
<div class="progress-bar-bg">
|
<div class="progress-bar-bg">
|
||||||
<div class="progress-bar" id="ram-bar"></div>
|
<div class="progress-bar" id="ram-bar" style="width: 0%"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card stat-card">
|
<div class="card stat-card">
|
||||||
<h3>Disk</h3>
|
<h3>Disk</h3>
|
||||||
<div class="stat-value" id="disk-val">--%</div>
|
<div class="stat-value" id="disk-val">--%</div>
|
||||||
<div class="progress-bar-bg">
|
<div class="progress-bar-bg">
|
||||||
<div class="progress-bar" id="disk-bar"></div>
|
<div class="progress-bar" id="disk-bar" style="width: 0%"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section-title">Ações Rápidas</div>
|
<div class="section-title">Ações Rápidas</div>
|
||||||
<div class="actions-grid">
|
<div class="actions-grid">
|
||||||
<button type="button" class="btn" aria-label="Ping" onclick="executeAction('ping')">
|
<button type="button" class="btn" onclick="executeAction('ping')">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M22 12h-4l-3 9L9 3l-3 9H2" />
|
<path d="M22 12h-4l-3 9L9 3l-3 9H2" />
|
||||||
</svg>
|
</svg>
|
||||||
Ping
|
Ping
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn" id="btn-test-llm" aria-label="Testar LLM" onclick="testLLMSpeed()">
|
<button type="button" class="btn" id="btn-test-llm" onclick="testLLMSpeed()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M12 2a10 10 0 1 0 10 10H12V2z" />
|
<path d="M12 2a10 10 0 1 0 10 10H12V2z" />
|
||||||
<path d="M12 2a10 10 0 0 1 10 10h-2a8 8 0 0 0-8-8V2z" />
|
<path d="M12 2a10 10 0 0 1 10 10h-2a8 8 0 0 0-8-8V2z" />
|
||||||
<path d="M12 12V2.5l5.5 5.5" />
|
<path d="M12 12V2.5l5.5 5.5" />
|
||||||
</svg>
|
</svg>
|
||||||
Testar LLM
|
Testar LLM
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn" aria-label="Reiniciar Bot" onclick="executeAction('restart_bot')">
|
<button type="button" class="btn" onclick="executeAction('restart_bot')">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M23 4v6h-6M1 20v-6h6" />
|
<path d="M23 4v6h-6M1 20v-6h6" />
|
||||||
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" />
|
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" />
|
||||||
</svg>
|
</svg>
|
||||||
Reiniciar
|
Reiniciar
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn" aria-label="Limpar Cache" onclick="executeAction('clear_cache')">
|
<button type="button" class="btn" onclick="executeAction('clear_cache')">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
|
<path
|
||||||
|
d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
|
||||||
</svg>
|
</svg>
|
||||||
Limpar Cache
|
Limpar Cache
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-danger" aria-label="Reboot VPS" onclick="executeAction('reboot_vps')">
|
<button type="button" class="btn btn-danger" onclick="executeAction('reboot_vps')">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
|
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
|
||||||
</svg>
|
</svg>
|
||||||
Reboot VPS
|
Reboot VPS
|
||||||
@@ -822,12 +747,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="gemini_api_key">Gemini API Key</label>
|
<label for="gemini_api_key">Gemini API Key</label>
|
||||||
<input type="password" id="gemini_api_key" autocomplete="new-password" aria-label="Gemini API Key"
|
<input type="password" id="gemini_api_key" autocomplete="new-password"
|
||||||
class="form-input" placeholder="AIzaSy...">
|
aria-label="Gemini API Key" class="form-input" placeholder="AIzaSy...">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-primary" aria-label="Salvar Configuração" onclick="saveConfiguration()">
|
<button type="button" class="btn btn-primary" onclick="saveConfiguration()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
|
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
|
||||||
<polyline points="17 21 17 13 7 13 7 21" />
|
<polyline points="17 21 17 13 7 13 7 21" />
|
||||||
<polyline points="7 3 7 8 15 8" />
|
<polyline points="7 3 7 8 15 8" />
|
||||||
@@ -842,25 +767,28 @@
|
|||||||
<div class="chat-wrapper">
|
<div class="chat-wrapper">
|
||||||
<div class="chat-messages" id="chat-box">
|
<div class="chat-messages" id="chat-box">
|
||||||
<div class="chat-bubble bubble-ai">
|
<div class="chat-bubble bubble-ai">
|
||||||
Olá! Sou o VPS Agent. Como posso ajudar com seu servidor? Tudo o que eu fizer aparecerá aqui no
|
Olá! Sou o VPS Agent. Como posso ajudar com seu servidor? Tudo o que eu fizer aparecerá aqui
|
||||||
|
no
|
||||||
terminal técnico.
|
terminal técnico.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chat-input-area">
|
<div class="chat-input-area" style="padding: 0.75rem; gap: 0.5rem;">
|
||||||
<input type="text" id="chat-input" aria-label="Comando do chat" class="chat-input"
|
<input type="text" id="chat-input" aria-label="Comando do chat" class="chat-input"
|
||||||
placeholder="Comande sua VPS aqui..." onkeypress="handleKeyPress(event)">
|
placeholder="Comande sua VPS aqui..." onkeypress="handleKeyPress(event)">
|
||||||
|
|
||||||
<button type="button" class="btn" id="audio-btn" aria-label="Gravar Áudio"
|
<button type="button" class="btn" id="audio-btn" aria-label="Gravar Áudio"
|
||||||
onclick="toggleRecording()" title="Gravar Áudio">
|
onclick="toggleRecording()" title="Gravar Áudio">
|
||||||
<svg id="mic-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
<svg id="mic-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" />
|
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" />
|
||||||
<path d="M19 10v2a7 7 0 0 1-14 0v-2M12 19v4M8 23h8" />
|
<path d="M19 10v2a7 7 0 0 1-14 0v-2M12 19v4M8 23h8" />
|
||||||
</svg>
|
</svg>
|
||||||
<span id="recording-dot" class="recording-indicator"></span>
|
<span id="recording-dot"
|
||||||
|
style="display:none; width:8px; height:8px; background:red; border-radius:50%; animation: pulse 1s infinite;">
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="btn btn-primary" aria-label="Enviar mensagem" onclick="sendChat()">
|
<button type="button" class="btn btn-primary" aria-label="Enviar" onclick="sendChat()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<line x1="22" y1="2" x2="11" y2="13" />
|
<line x1="22" y1="2" x2="11" y2="13" />
|
||||||
<polygon points="22 2 15 22 11 13 2 9 22 2" />
|
<polygon points="22 2 15 22 11 13 2 9 22 2" />
|
||||||
</svg>
|
</svg>
|
||||||
@@ -871,7 +799,7 @@
|
|||||||
<!-- Coluna 2: Painel de Insights (Refinado) -->
|
<!-- Coluna 2: Painel de Insights (Refinado) -->
|
||||||
<div class="insights-wrapper">
|
<div class="insights-wrapper">
|
||||||
<div class="insights-header">
|
<div class="insights-header">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18">
|
||||||
<path d="M21 12V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h7" />
|
<path d="M21 12V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h7" />
|
||||||
<line x1="16" y1="5" x2="16" y2="19" />
|
<line x1="16" y1="5" x2="16" y2="19" />
|
||||||
<line x1="2" x2="16" y2="12" />
|
<line x1="2" x2="16" y2="12" />
|
||||||
@@ -880,14 +808,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="insights-content" id="insights-panel">
|
<div class="insights-content" id="insights-panel">
|
||||||
<div class="insights-placeholder">
|
<div class="insights-placeholder">
|
||||||
<div class="insights-icon" role="img" aria-label="Gráfico de Insights">📊</div>
|
<div style="font-size: 2.5rem; margin-bottom: 1rem;" role="img"
|
||||||
|
aria-label="Gráfico de Insights">📊</div>
|
||||||
<p>Aguardando dados estruturados...</p>
|
<p>Aguardando dados estruturados...</p>
|
||||||
<small>Peça algo como "status dos containers" para ver o refinamento aqui.</small>
|
<small style="display:block; margin-top:0.5rem; opacity:0.6;">Peça algo como "status dos
|
||||||
|
containers" para ver o refinamento aqui.</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="toast">Ação executada!</div>
|
<div id="toast">Ação executada!</div>
|
||||||
|
|
||||||
@@ -947,11 +878,15 @@
|
|||||||
updateThemeIcon(!isDark);
|
updateThemeIcon(!isDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateThemeIcon(isDark) {}
|
function updateThemeIcon(isDark) {
|
||||||
|
document.getElementById('icon-sun').style.display = isDark ? 'block' : 'none';
|
||||||
|
document.getElementById('icon-moon').style.display = isDark ? 'none' : 'block';
|
||||||
|
}
|
||||||
|
|
||||||
const savedTheme = localStorage.getItem('theme');
|
const savedTheme = localStorage.getItem('theme');
|
||||||
if (savedTheme) {
|
if (savedTheme) {
|
||||||
document.documentElement.dataset.theme = savedTheme;
|
document.documentElement.dataset.theme = savedTheme;
|
||||||
|
updateThemeIcon(savedTheme === 'light');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stats
|
// Stats
|
||||||
@@ -1196,9 +1131,9 @@
|
|||||||
const icon = document.getElementById('mic-icon');
|
const icon = document.getElementById('mic-icon');
|
||||||
const btn = document.getElementById('audio-btn');
|
const btn = document.getElementById('audio-btn');
|
||||||
|
|
||||||
if (dot) dot.style.display = active ? 'inline-block' : 'none';
|
dot.style.display = active ? 'inline-block' : 'none';
|
||||||
if (icon) icon.style.color = active ? 'red' : 'inherit';
|
icon.style.color = active ? 'red' : 'inherit';
|
||||||
if (btn) btn.style.borderColor = active ? 'red' : 'var(--border)';
|
btn.style.borderColor = active ? 'red' : 'var(--border)';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadAudio(blob) {
|
async function uploadAudio(blob) {
|
||||||
|
|||||||
Reference in New Issue
Block a user