O celular adormece sozinho (silêncio sem movimento) e acorda com som, movimento ou toque; isso vem na telemetria, não no SSE de ordens, e a prévia do painel continuava acordada. Ao vivo e mini-rosto agora seguem o `dormindo` da telemetria; as prévias de edição (Rosto, Reações) não. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
82 lines
2.8 KiB
Svelte
82 lines
2.8 KiB
Svelte
<script lang="ts">
|
|
/**
|
|
* Prévia do rosto: o próprio carinha.html em modo ?painel=1 (sem polling).
|
|
* O painel repassa por postMessage o que chega no SSE, então a prévia mostra
|
|
* exatamente as mesmas ordens que o celular recebe.
|
|
*/
|
|
import { onDestroy } from 'svelte';
|
|
import { estado, ouvir } from '../estado.svelte';
|
|
|
|
/** espelharSono: dorme/acorda junto com o celular (ele adormece sozinho no silêncio). */
|
|
let { titulo = 'Prévia do rosto', espelharSono = true }: { titulo?: string; espelharSono?: boolean } = $props();
|
|
let quadro: HTMLIFrameElement;
|
|
let pronto = $state(false);
|
|
|
|
function enviar(msg: unknown) {
|
|
if (pronto) quadro?.contentWindow?.postMessage(msg, location.origin);
|
|
}
|
|
|
|
function aoCarregar() {
|
|
pronto = true;
|
|
if (estado.appConfig) enviar({ tipo: 'config', config: $state.snapshot(estado.appConfig) });
|
|
}
|
|
|
|
// Sono que o celular decidiu sozinho (silêncio, toque, barulho) não passa pelo SSE de ordens:
|
|
// vem na telemetria. Sem celular online, a prévia fica como está.
|
|
const dormindoNoCelular = $derived(estado.celularOnline ? !!estado.app?.estado?.dormindo : null);
|
|
$effect(() => {
|
|
if (espelharSono && pronto && dormindoNoCelular !== null) enviar({ tipo: 'sono', dormindo: dormindoNoCelular });
|
|
});
|
|
|
|
let ultimaConversa = estado.conversa?.ultima?.id;
|
|
const cancelar = [
|
|
ouvir('expressao', (d) => enviar({ tipo: 'ordem', ordem: d.ordem })),
|
|
ouvir('app_config', (c) => enviar({ tipo: 'config', config: c })),
|
|
ouvir('reacao', (r) => r?.receita && enviar({ tipo: 'previa-reacao', receita: r.receita })),
|
|
// O celular reage à resposta da conversa com acordar + gesto; a prévia imita.
|
|
ouvir('conversa', (c) => {
|
|
if (c.ultima && c.ultima.id !== ultimaConversa) {
|
|
ultimaConversa = c.ultima.id;
|
|
enviar({ tipo: 'ordem', ordem: 'acordar' });
|
|
enviar({ tipo: 'ordem', ordem: c.ultima.gesto });
|
|
enviar({ tipo: 'legenda', texto: c.ultima.texto });
|
|
}
|
|
}),
|
|
];
|
|
onDestroy(() => cancelar.forEach((c) => c()));
|
|
|
|
/** Mostra uma ordem (gesto, rosto, formato) só na prévia, sem mandar ao celular. */
|
|
export function ordem(texto: string) {
|
|
enviar({ tipo: 'ordem', ordem: texto });
|
|
}
|
|
|
|
/** Mostra uma legenda na faixa de baixo da prévia. */
|
|
export function legenda(texto: string) {
|
|
enviar({ tipo: 'legenda', texto });
|
|
}
|
|
|
|
/** Para a tela de reações: mostra uma receita sem mandar ao celular. */
|
|
export function previa(receita: unknown) {
|
|
enviar({ tipo: 'previa-reacao', receita });
|
|
}
|
|
</script>
|
|
|
|
<iframe
|
|
bind:this={quadro}
|
|
src="/carinha.html?espelho=1&painel=1&auto=0&camera=0&audio=0"
|
|
title={titulo}
|
|
tabindex="-1"
|
|
onload={aoCarregar}
|
|
></iframe>
|
|
|
|
<style>
|
|
iframe {
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
border: 0;
|
|
background: #000;
|
|
border-radius: inherit;
|
|
}
|
|
</style>
|