Skip to main content

Plano de conformidade — ADR-0009 seleção e cópia de texto

Referência: ADR-0009, seção 8 — Seleção e cópia de texto
Regra: Texto somente leitura (labels, mensagens, conteúdo de cards, etc.) deve ser selecionável (SelectableText).
Exceções: (1) Textos puramente decorativos ou de um único caractere (ex.: iniciais em avatar) permanecem Text. (2) Textos de botões (labels de TextButton, FilledButton, OutlinedButton, ChoiceChip, itens de dropdown/menu clicável) permanecem Text, para não interferir na usabilidade do toque/clique (ADR-0009 atualizado).


Escopo da alteração

  • Substituir Text(...) por SelectableText(...) em todo conteúdo legível pelo usuário.
  • Manter Text apenas onde for exceção (decorativo / um caractere, ex. iniciais em avatar).
  • SnackBars e diálogos: conteúdo de mensagem em SelectableText; labels de botões (e elementos clicáveis como ChoiceChip, itens de dropdown) em Text para não interferir na usabilidade.

Camada afetada: apenas presentation (Flutter). Nenhuma alteração em domain, application ou infrastructure.


Ordem de execução

Sugestão: por módulo, da base (widgets compartilhados e shell) para páginas e diálogos, para poder reutilizar padrões.

#Módulo / arquivoItensPrioridade
1home_shell_widgets.dartAbas, rodapéBase
2login_page.dartDialogs, SnackBars, labels, AppBarAlta
3register_page.dartDialogs, SnackBars, labels, listas de validaçãoAlta
4home_page.dartDialog igreja, SnackBars, card principal, versãoAlta
5home_profile_dialog.dartTítulo "Perfil", label "Sair"Média
6home_profile_dialog_actions.dartSnackBars, títulos de diálogo, mensagens, botões de opçãoMédia
7home_profile_dialog_avatar.dartTítulos e conteúdos de diálogos (troca igreja, motivo); manter Text só para iniciaisMédia
8home_profile_dialog_tabs.dartLabels, "Cargo atual", solicitações, mensagens, dropdown temaMédia
9avatar_viewer_dialog.dartTexto "Zoom X.XXx"; manter Text para iniciaisBaixa
10debug_help_popup.dartTítulos, labels, sessão, documentação de ajudaBaixa (debug)

Detalhamento por arquivo

1. presentation/pages/home/widgets/home_shell_widgets.dart

LocalAtualAção
Labels das abas (_tabs[index])TextSelectableText
Rodapé "Fiel a todo momento"TextSelectableText
"EBDbe v$version"TextSelectableText

2. presentation/pages/login/login_page.dart

LocalAtualAção
SnackBar "Bem-vindo...", erro, "Login com Google indisponível...", etc.TextSelectableText (conteúdo do SnackBar)
Dialog recuperar conta: título "Recuperar conta"TextSelectableText
Dialog: corpo "Informe seu email..."TextSelectableText
Botões "Cancelar", "Enviar link"TextSelectableText (ou manter se preferir só conteúdo longo selecionável)
Mensagens de sucesso/erro no dialogTextSelectableText
AppBar title "Entrar"TextSelectableText
"Esqueci minha senha"TextSelectableText
"Ainda não tem conta?"TextSelectableText
"Criar conta" (botão)TextSelectableText
"ou:"SelectableTextManter

3. presentation/pages/login/register_page.dart

LocalAtualAção
Lista de validação: "$title: $compactLine", "falta atender:", "• $item"TextSelectableText
Conteúdo de todos os dialogs (Firebase, "Conta autenticada...", "Preencha Nome e Igreja...", link verificação, "Já existe cadastro...", etc.)TextSelectableText
SnackBars (erro, sucesso, "Preencha...", "Reenviando...", etc.)TextSelectableText
"Tentar novamente", "Cadastrar com email", "Reenviar email de confirmacao"TextSelectableText
AppBar "Criar conta"TextSelectableText
Hint do campo (se for texto estático legível)AvaliarSelectableText se for mensagem longa
Já em SelectableTextManter

4. presentation/pages/home/home_page.dart

LocalAtualAção
Dialog igreja: title "Selecione sua igreja"TextSelectableText
Dialog igreja: corpo longoTextSelectableText
Lista: item.labelTextSelectableText
Botões "Cancelar", "Concluir"TextSelectableText
Alert "Login indisponível..."TextSelectableText
SnackBar _profileErrorTextSelectableText
Botão "Entrar" / "Entrar (indisponível)"TextSelectableText
Iniciais no avatarText(initial.toUpperCase())Manter Text (exceção)
SnackBar "Publicação: $fullLabel"TextSelectableText
"v$_appVersion"TextSelectableText
Card: "EBDbe", "EBD", "Escola Bíblica Dominical", "Igreja Batista Ebenézer...", "EBD aos domingos...", profileSubtitle, "Ações", "Conheça a Ebenézer"TextSelectableText

5. presentation/modules/profile_dialog/home_profile_dialog.dart

LocalAtualAção
Título "Perfil"TextSelectableText
Label "Sair"TextSelectableText

6. presentation/modules/profile_dialog/home_profile_dialog_actions.dart

LocalAtualAção
SnackBars ("Atualizado com sucesso.", error.message, "Falha ao processar...")TextSelectableText
Opções do bottom sheet: "Usar URL da foto", "Usar câmera", "Escolher da galeria"TextSelectableText
Dialog URL: title "URL da foto"TextSelectableText
Botões "Cancelar", "Usar foto"TextSelectableText
Mensagem "Não foi possível selecionar a imagem..."TextSelectableText

7. presentation/modules/profile_dialog/home_profile_dialog_avatar.dart

LocalAtualAção
Iniciais no avatarText(initials)Manter Text (exceção)
Dialog troca igreja: title "Confirmar troca de igreja"TextSelectableText
Conteúdo "Você está trocando sua igreja..."TextSelectableText
Botões "Não", "Sim"TextSelectableText
Alert "Informe o motivo da solicitação de perfil."TextSelectableText

8. presentation/modules/profile_dialog/home_profile_dialog_tabs.dart

LocalAtualAção
Label de item (lista de igrejas/unidades)Text(item.label)SelectableText
Dialog troca igreja: title "Troca de igreja", conteúdo, "Entendi"TextSelectableText
Labels "Colar URL e salvar", "Galeria", "Câmera"TextSelectableText
"Cargo atual de operação: $currentRoleLabel"TextSelectableText
"Nenhum cargo aprovado ainda."TextSelectableText
Labels de role no dropdown/chipText(roleLabels[roleId] ?? roleId)SelectableText
Parágrafo "Solicitar perfil acima do atual exige aprovação..."TextSelectableText
displayLabel em itens de listaText(item.displayLabel)SelectableText
"Solicitações recentes"TextSelectableText
Título e subtítulo de solicitação (roleLabels, status, data)TextSelectableText
"Destaques (nível imediatamente abaixo)", "Demais mensagens agrupadas"TextSelectableText
message.title, message.bodyTextSelectableText
"Sem mensagens no momento."TextSelectableText
Dropdown tema: "Default", "Light", "Dark", "Sepia"TextSelectableText

9. presentation/modules/profile_dialog/avatar_viewer_dialog.dart

LocalAtualAção
Iniciais no placeholderText(widget.initials)Manter Text (exceção)
"Zoom X.XXx" (valor dinâmico)TextSelectableText

10. presentation/widgets/debug_help_popup.dart

LocalAtualAção
SnackBarsTextSelectableText
"Nível de debug", labels de nívelTextSelectableText
"Debug out", "Atualizar", "Limpar", "Copiar saída"TextSelectableText
"Comandos", "Limpar", "Injetar papéis:", "1. Catálogo...", "2. Visibilidade...", "Executar comando"TextSelectableText
"Atalhos 0–9", índices "0"-"9"TextSelectableText
"Sessão: ..."TextSelectableText
"Ajuda do aplicativo", bloco de documentaçãoTextSelectableText
Saída de debugSelectableTextManter

Regras ao implementar

  1. Semântica: usar SelectableText com os mesmos parâmetros de estilo que o Text original (style, textAlign, maxLines, overflow quando fizer sentido).
  2. Const: onde hoje é const Text('...'), usar const SelectableText('...') quando o conteúdo for literal.
  3. Interpolação: onde há Text('... $var ...'), usar SelectableText('... $var ...') (sem const).
  4. SnackBar: SnackBar(content: SelectableText(...)) — garantir que o conteúdo seja widget único ou que o primeiro filho seja o texto selecionável.
  5. Não alterar: TextField, TextFormField, hint (é parte do input); apenas não bloquear cola neles (já é padrão).
  6. Exceções explícitas: manter Text apenas para iniciais em avatar e textos de um caractere/decorativos.

Validação

  • Após cada arquivo (ou lote): fvm flutter analyze e checagem visual na tela.
  • Ao final: percorrer cada tela e conferir que texto legível permite seleção/cópia (gesto longo ou Ctrl+C no web).
  • Documentar no próprio ADR ou neste plano que a conformidade foi concluída (data e escopo).

Conclusão da execução

  • Data: 2025-03-01
  • Branch: feat/adr-0009-selectable-text
  • Escopo: Todos os 10 arquivos do plano alterados; texto legível passou a usar SelectableText; exceções (iniciais em avatar) mantidas como Text.
  • Validação: fvm flutter analyze OK (apenas warning pré-existente em _hasAvatarDraft).

Estimativa

  • Itens 1–4 (shell + login + register + home): ~40 substituições.
  • Itens 5–8 (profile dialog): ~50 substituições.
  • Itens 9–10 (viewer + debug): ~15 substituições.
    Total aproximado: ~105 pontos de alteração. Pode ser feita em uma única branch (ex.: feat/adr-0009-selectable-text) ou em commits por arquivo/módulo.