Skip to content

Engine/Mobile: Enter não auto-indenta a linha seguinte — indentar no teclado virtual é espaço a espaço (CodeEditor.tsx:139) #62

Closed

Description

@caioross

Fricção nº3 do relato da persona Mobile (Discussion #45), que ficou na fila do chapéu de Engine: "teclado virtual não tem Tab, e o Enter não auto-indenta a linha seguinte — tenho que bater espaço-espaço na mão em cada linha". ICE ≈ 36 (Impacto 3 × Confiança 4 × Facilidade 3) → P3.

O estado hoje

A #41 resolveu a indentação no desktop: Tab preenche exatamente os espaços que o target espera na linha lógica atual, via a função pura indentEdit (src/lib/indent.ts:39), chamada no onKeyDown do editor (CodeEditor.tsx:138-149). É a abordagem certa — o editor não é um IDE genérico, o único texto "certo" é o snippet.

O problema: onKeyDown só trata Tab (CodeEditor.tsx:139 — if (e.key !== "Tab") return). No touch não existe Tab, então em snippets com aninhamento (2/4/6 espaços — praticamente todo medium/hard, e Python em qualquer nível) o jogador de celular digita a indentação espaço a espaço. Custa WPM e paciência exatamente onde a spec já marcou o mobile como crítico (docs/UI-AAA-OVERHAUL.md §III).

Acceptance criteria

  • Ao pressionar Enter no editor da corrida, a quebra de linha vem acompanhada da indentação que o target espera na linha seguinte — exatamente ela, nem um espaço a mais.
  • Zero regressão de honestidade: os espaços inseridos batem char-a-char com o alvo, então não acendem erro nem baixam a precisão (mesma garantia que o Tab já dá). node scripts/validate-metrics.mjs verde e os testes de src/lib/metrics.test.ts intactos.
  • No-op honesto nos casos de borda, sem inserir lixo: jogador com erro anterior (índices divergentes), linha seguinte sem indentação, caret no meio da linha, target com menos linhas que o digitado. Cobrir esses casos no suite de indent (Vitest já instalado pela Testes: instalar Vitest + primeiro suite na fronteira anti-cheat (sanitizeResults) e rodar no CI #31).
  • Caret fica depois da indentação inserida (mesma restauração via pendingCaret que o Tab usa, CodeEditor.tsx:69-77).
  • Área sagrada: nenhum trabalho novo por keystroke comum — o caminho só roda no Enter, e continua um único onChange/re-render, como o Tab.
  • Verificação declarada no PR: se o comportamento do Enter em teclado virtual não foi testado em aparelho físico, dizer isso explicitamente (a [Feedback] O Mobile · 2026-07-18 #45 foi honesta sobre o método; mantenha o padrão).

Dica de abordagem

indentEdit já resolve isso quase de graça, porque calcula a indentação pela linha lógica (nº de \n antes do caret, indent.ts:58-68) e não pelo offset cru. Então basta inserir o \n primeiro e perguntar a ela o que falta na linha nova:

// dentro do onKeyDown, ramo Enter
const withNl = value.slice(0, start) + "\n" + value.slice(end);
const { text, caret } = indentEdit(withNl, target, start + 1);
// text === withNl → sem indentação a preencher: deixe o Enter nativo seguir

Reusar a função pura em vez de escrever uma segunda lógica de indentação é o ponto central: uma fonte de verdade, um suite de testes, e o mesmo imunizante contra divergência de índice.

Risco a validar: alguns IMEs de teclado virtual (sobretudo Android) emitem keydown com keyCode 229/key: "Unidentified" em vez de "Enter". Se o ramo não disparar nesses teclados, o resultado deve ser o comportamento de hoje (Enter nativo, sem indentação) — degradação silenciosa, nunca texto errado. Diga no PR o que foi verificado e o que ficou como suposição.

Nota do relato que segue valendo como restrição intocável: autocorrect/autocapitalize/spellcheck desligados no campo (CodeEditor.tsx:318-321) — não mexer.

Activity

  1. added
    P3Algum dia / baixo impacto
    area:engineMotor de digitação, WPM, precisão, anti-cheat
    area:uiInterface, design system, animação, game feel
    em-resolucaoClaim: um Resolvedor está trabalhando nisto
    and removed
    em-resolucaoClaim: um Resolvedor está trabalhando nisto
    on Jul 24, 2026
  2. caioross commented on Jul 26, 2026

    @caioross
    OwnerAuthor

    Resolvida em #87 — #87

    enterEdit puro em src/lib/indent.ts reusa o indentEdit (mesma fonte de verdade do Tab): insere o \n e preenche a indentação exata que o target espera na linha seguinte; no-op honesto (linha rasa, erro anterior, caret no meio, target curto) → Enter nativo, nunca lixo. CodeEditor.onKeyDown trata Enter além do Tab, com guarda isComposing.

    Gate verde: typecheck ✅ · build ✅ · pnpm test 64 (novo indent.test.ts com 10) · validate-metrics 45 (+8 casos de Enter). AC #6 honesto: a lógica pura está coberta por 18 casos, mas o comportamento em teclado virtual físico não foi testado (sem device); IMEs que emitem keyCode 229 caem no Enter nativo — detalhado no PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Algum dia / baixo impactoarea:engineMotor de digitação, WPM, precisão, anti-cheatarea:uiInterface, design system, animação, game feel

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions