/** Ajustes do app do celular (/app/config): salvamento otimista e campos agrupados. */ import { pedir, postar } from './api'; import { avisos } from './avisos.svelte'; import { estado } from './estado.svelte'; import type { AppConfig } from './tipos'; /** Atualiza na hora; se o servidor recusar, volta ao valor anterior e avisa. Não trava o formulário. */ export async function salvarApp(parcial: AppConfig) { const antes = estado.appConfig ? { ...estado.appConfig } : null; if (estado.appConfig) estado.appConfig = { ...estado.appConfig, ...parcial }; try { const r = await postar<{ config: AppConfig }>('/app/config', parcial); estado.appConfig = r.config; } catch (e) { estado.appConfig = antes; avisos.erro(e); } } export async function restaurarPadrao() { const padrao = await pedir('/app/padrao'); // A transmissão não é "ajuste": continua como está. delete padrao.preview; await salvarApp(padrao); avisos.ok('Ajustes do celular restaurados para o padrão.'); } type Opcoes = [string | number, string][]; export interface Campo { chave: string; rotulo: string; ajuda?: string; tipo: 'toggle' | 'slider' | 'escolha'; min?: number; max?: number; passo?: number; unidade?: string; opcoes?: Opcoes; } export const GRUPOS: { titulo: string; descricao: string; campos: Campo[] }[] = [ { titulo: 'Tela e personalidade', descricao: 'Como o rosto aparece e se comporta sozinho.', campos: [ { chave: 'auto', rotulo: 'Gestos espontâneos', ajuda: 'Pisca e olha em volta sem comando', tipo: 'toggle' }, { chave: 'boca', rotulo: 'Mostrar boca', tipo: 'toggle' }, { chave: 'sobrancelhas', rotulo: 'Mostrar sobrancelhas', tipo: 'toggle' }, { chave: 'audio', rotulo: 'Sons no celular', ajuda: 'Bipes do próprio robô', tipo: 'toggle' }, { chave: 'volume', rotulo: 'Volume dos sons', tipo: 'slider', min: 0, max: 1, passo: 0.05 }, { chave: 'brilho', rotulo: 'Brilho normal', tipo: 'slider', min: 0.01, max: 1, passo: 0.01 }, { chave: 'economia', rotulo: 'Reduzir brilho em repouso', tipo: 'toggle' }, { chave: 'brilhoRepouso', rotulo: 'Brilho em repouso', tipo: 'slider', min: 0.01, max: 1, passo: 0.01 }, { chave: 'repousoTela', rotulo: 'Espera para reduzir brilho', tipo: 'slider', min: 5, max: 300, passo: 5, unidade: ' s' }, ], }, { titulo: 'Sensores e reações', descricao: 'O que o celular percebe e como reage.', campos: [ { chave: 'sensorMic', rotulo: 'Microfone', ajuda: 'Só o nível de som é usado, nunca o áudio', tipo: 'toggle' }, { chave: 'ouvir', rotulo: 'Reagir a sons', tipo: 'toggle' }, { chave: 'micSono', rotulo: 'Microfone durante o sono', tipo: 'toggle' }, { chave: 'sompausa', rotulo: 'Silêncio para dormir', tipo: 'slider', min: 1, max: 120, passo: 1, unidade: ' s' }, { chave: 'sensorCamera', rotulo: 'Câmera como sensor', ajuda: 'Detecta movimento e permite o vídeo', tipo: 'toggle' }, { chave: 'reagir', rotulo: 'Reagir a movimento', tipo: 'toggle' }, { chave: 'cameraSono', rotulo: 'Câmera durante o sono', tipo: 'toggle' }, { chave: 'movolhar', rotulo: 'Quanto os olhos acompanham', tipo: 'slider', min: 0, max: 100, passo: 1, unidade: '%' }, ], }, { titulo: 'Vídeo e rastreamento', descricao: 'Qualidade da transmissão e rastreamento feito neste PC.', campos: [ { chave: 'cameraLado', rotulo: 'Câmera', tipo: 'escolha', opcoes: [['user', 'Frontal'], ['environment', 'Traseira']] }, { chave: 'videoResolucao', rotulo: 'Resolução', tipo: 'escolha', opcoes: [['auto', 'Automática'], ['max', 'Máxima'], ['480', '480p'], ['720', '720p'], ['1080', '1080p'], ['2160', '4K'], ['4320', '8K']], }, { chave: 'videoFPS', rotulo: 'Quadros por segundo', tipo: 'escolha', opcoes: [[0, 'Automático'], [-1, 'Máximo'], [15, '15'], [24, '24'], [30, '30'], [60, '60'], [120, '120'], [240, '240']], }, { chave: 'rastrearRosto', rotulo: 'Rastrear rosto', tipo: 'toggle' }, { chave: 'rastrearMaos', rotulo: 'Rastrear mãos', tipo: 'toggle' }, { chave: 'seguirRastreamento', rotulo: 'Olhos seguem o alvo', tipo: 'toggle' }, { chave: 'mostrarRastreamento', rotulo: 'Desenhar rastreamento no vídeo', tipo: 'toggle' }, ], }, { titulo: 'Sensibilidade (avançado)', descricao: 'Limiares dos sustos e intervalos entre reações.', campos: [ { chave: 'somlim', rotulo: 'Nível para perceber som', tipo: 'slider', min: 0, max: 1, passo: 0.01 }, { chave: 'somaltolim', rotulo: 'Som mínimo para susto', tipo: 'slider', min: 0, max: 1, passo: 0.01 }, { chave: 'somganho', rotulo: 'Aumento súbito para susto', tipo: 'slider', min: 0, max: 1, passo: 0.01 }, { chave: 'somcooldown', rotulo: 'Intervalo entre sustos por som', tipo: 'slider', min: 0, max: 120, passo: 1, unidade: ' s' }, { chave: 'movlim', rotulo: 'Movimento mínimo', tipo: 'slider', min: 0, max: 1, passo: 0.01 }, { chave: 'movforte', rotulo: 'Movimento para susto', tipo: 'slider', min: 0, max: 1, passo: 0.01 }, { chave: 'movcooldown', rotulo: 'Intervalo entre sustos por movimento', tipo: 'slider', min: 0, max: 120, passo: 1, unidade: ' s' }, ], }, ];