Files
carinha-control-panel/web/src/lib/componentes/Gestos.svelte
T
julioandClaude Opus 5.5 05e82dfd75 feat(criacao): estúdio para criar expressões, atividades e figurinhas com IA
Menu "Criar com IA" (Ao vivo › Gestos e Reações) com grade igual à dos
favoritos. Para cada pedido escolhe-se o tipo (expressão, atividade ou
figurinha) e a IA: Gemini, IA local (qualquer servidor compatível com
OpenAI na rede, como o ROG Ally com LM Studio/llama-server) ou o Qwen do S10.

- A IA não escreve código: responde uma receita de formato fixo (schema
  JSON) montada só com peças que o rosto já anima. O servidor valida,
  limita números e descarta peças desconhecidas antes de chegar ao celular.
- Reaproveita o que existe: o prompt leva exemplos reais dos gestos e
  atividades atuais, e "Basear em" manda a receita de um gesto, atividade
  ou criação para a IA fazer uma variação.
- Expressões viram sequências como as de sequencias(), com mãos e espiral.
- Atividades usam uma cena genérica com o bonequinho (poses, pernas, pulo,
  balanço) e os objetos das cenas feitas à mão (bola, livro, xícara,
  notas, estrelas, coração, Zzz, chama, bolha, halter, microfone,
  controle, pincel, flor), com movimentos pular/girar/subir/orbitar.
- Figurinhas reaproveitam o desenho e a biblioteca de reações.
- A estrela põe expressões e atividades criadas nos favoritos (e nas
  teclas 1 a 9); a IA local é configurada na própria tela, com teste.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:22:52 -03:00

120 lines
3.2 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts">
import { Star } from '@lucide/svelte';
import { favoritos, GESTOS_INFO, gestosDisponiveis, tocarFavorito } from '../comandos.svelte';
import { criacao } from '../criacao.svelte';
// compacto: só os favoritos com atalho 1–9 (dock), inclusive criações do estúdio. Completo: todos, com estrela.
let { completo = false }: { completo?: boolean } = $props();
$effect(() => {
if (!completo && !criacao.status && favoritos.lista.some((g) => g.startsWith('criado:'))) criacao.carregar();
});
function infoDe(g: string) {
if (g.startsWith('criado:')) {
const c = criacao.item(Number(g.slice(7)));
return c ? { nome: c.nome, emoji: c.emoji } : null;
}
return GESTOS_INFO[g] ?? null;
}
const lista = $derived(completo ? gestosDisponiveis() : favoritos.lista.filter((g) => infoDe(g)));
</script>
<div class="gestos" class:completo>
{#each lista as g, i (g)}
{@const info = infoDe(g)!}
<div class="item">
<button class="gesto" class:criado={g.startsWith('criado:')} onclick={() => tocarFavorito(g)} title={completo || i > 8 ? info.nome : `${info.nome} (tecla ${i + 1})`}>
<span class="emoji" aria-hidden="true">{info.emoji}</span>
<span class="nome">{info.nome}</span>
{#if !completo && i < 9}<kbd>{i + 1}</kbd>{/if}
</button>
{#if completo}
<button
class="estrela"
class:ativa={favoritos.lista.includes(g)}
aria-label={favoritos.lista.includes(g) ? `Tirar ${info.nome} dos favoritos` : `Fixar ${info.nome} nos favoritos`}
aria-pressed={favoritos.lista.includes(g)}
onclick={() => favoritos.alternar(g)}
>
<Star size={14} />
</button>
{/if}
</div>
{/each}
</div>
<style>
.gestos {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
gap: var(--e-2);
}
.item {
position: relative;
}
.gesto {
width: 100%;
display: grid;
justify-items: center;
gap: 2px;
padding: var(--e-3) var(--e-1) var(--e-2);
border: 1px solid var(--borda);
border-radius: var(--raio);
background: var(--superficie-2);
color: var(--texto);
font: inherit;
cursor: pointer;
position: relative;
transition: background var(--transicao), border-color var(--transicao), transform var(--transicao);
}
.gesto:hover {
border-color: var(--destaque);
background: var(--destaque-suave);
}
.gesto:active {
transform: scale(0.97);
}
.emoji {
font-size: 1.6rem;
line-height: 1.2;
}
.nome {
font-size: var(--t-xs);
color: var(--texto-2);
text-align: center;
}
.gesto.criado::after {
content: '✨';
position: absolute;
left: 6px;
top: 4px;
font-size: 10px;
}
kbd {
position: absolute;
top: 4px;
right: 6px;
font: 500 10px var(--fonte-mono);
color: var(--texto-3);
}
.estrela {
position: absolute;
top: 2px;
right: 2px;
width: 26px;
height: 26px;
display: grid;
place-items: center;
border: 0;
border-radius: 50%;
background: transparent;
color: var(--texto-3);
cursor: pointer;
}
.estrela.ativa {
color: var(--aviso);
}
.estrela.ativa :global(svg) {
fill: currentColor;
}
</style>