Skip to content

Músicas

Gerado pelo Writer (Reversa) em 2026-05-11 doc_level: detalhado | Granularidade: híbrida (módulo + casos de uso)

Visão Geral

Núcleo do produto. O módulo de Músicas expõe o catálogo de cânticos litúrgicos — somente-leitura para o usuário — e oferece busca textual avançada por FTS5, visualização da letra com keep-awake, favoritos, histórico de músicas vistas e reporte de erros. É o ponto de entrada principal do app.

Responsabilidades

  • Buscar músicas por texto livre (FTS5), por índice numérico no livro selecionado ou sem filtro (listagem completa)
  • Exibir a letra completa de uma música com destaque do termo buscado
  • Persistir localmente músicas favoritas e histórico de visualizações
  • Impedir que a tela dorme enquanto a letra está sendo lida (Keep Awake)
  • Permitir reporte de erros de conteúdo para a equipe via Airtable

Regras de Negócio

  • O catálogo de músicas é somente-leitura para o usuário — nunca editado diretamente no app 🟢
  • Uma música pode ter múltiplos vídeos YouTube (YouTubes[]); o campo singular YouTube está deprecated e mantido por compatibilidade 🟢
  • A busca FTS5 ignora acentos (normalização NFKD) e faz match por prefixo (* no final de cada token) 🟢
  • Busca por número inteiro é interpretada como busca por índice no livro selecionado, não como busca textual 🟢
  • A tela de letra usa Keep Awake — a tela do dispositivo não dorme enquanto o usuário lê 🟢
  • Músicas de Salmo têm tratamento especial na pré-visualização da letra (sanitização diferenciada) 🟡
  • Relatar erro abre formulário Airtable pré-preenchido com id_musica, título e início da letra 🟢
  • Favoritar uma música não altera o estado em memória imediatamente — a operação é apenas persistida no SQLite 🟢
  • Ao carregar a tela de letra, marcarAsVisualizada é disparado como side effect assíncrono, sem bloquear a UI 🟢
  • O campo informacoes (JSON livre, v9) existe no schema mas não é exibido na UI — campo de extensão futura 🟡
  • Snippets de destaque FTS5 usam marcadores || e são limitados a TOTAL_TOKENS (12 no phone, 24 no tablet) 🟢

Requisitos Funcionais

| ID | Requisito | Prioridade | Critério de Aceite | | ----- | ------------------------------------------------------------------------- | ---------- | ----------------------------------------------------------------------------------------- | --- | -------------------------------------- | | RF-01 | Listar músicas do catálogo com paginação por offset/limit | Must | Lista carrega corretamente; hasNextPage é verdadeiro quando há mais resultados | | RF-02 | Busca textual por FTS5 com normalização de acentos e match por prefixo | Must | "ave maria" encontra "Avé Maria" e "Avé Marias" | | RF-03 | Busca por índice numérico no livro selecionado | Must | Digitar "23" retorna a música de índice 23 no livro ativo | | RF-04 | Exibir letra completa com destaque do termo buscado | Must | Marcadores | | são renderizados com destaque visual | | RF-05 | Filtrar músicas por edição de livro selecionada | Must | Apenas músicas do livro selecionado aparecem na listagem | | RF-06 | Filtrar músicas por rótulo litúrgico | Should | Selecionar "Entrada" exibe somente músicas com esse rótulo | | RF-07 | Favoritar e desfavoritar música localmente | Must | Favorito persiste entre sessões; ícone reflete estado correto | | RF-08 | Manter histórico das últimas músicas visualizadas em "Visto recentemente" | Must | Visualizar uma música a adiciona no repertório padrão id=2 | | RF-09 | Impedir bloqueio de tela enquanto a letra está visível (Keep Awake) | Should | Tela permanece ativa durante leitura sem interação do usuário | | RF-10 | Exibir múltiplos vídeos YouTube de uma música | Should | Músicas com YouTubes[] exibem seletor de vídeo; músicas sem vídeo não exibem o player | | RF-11 | Abrir link CifraClub e/ou Partitura quando disponível | Could | Botão é exibido apenas quando o campo está preenchido | | RF-12 | Relatar erro de conteúdo via Airtable pré-preenchido | Could | Formulário abre com id_musica, titulo e inicio_da_letra pré-populados | | RF-13 | Exibir configuração adaptativa de tela (phone vs tablet) | Should | No tablet, TOTAL_CARACTERES=250 e TOTAL_TOKENS=24; no phone, 100 e 12 respectivamente |

Requisitos Não Funcionais

Tipo Requisito inferido Evidência no código Confiança
Performance Paginação offset/limit com LIMIT n+1 para detectar próxima página MusicasRepository.findAllBy — cláusula LIMIT 🟢
Performance Busca FTS5 com ranking bm25 (título peso 50, letra peso 5) MusicasRepository.findAllBy — ORDER BY bm25 🟢
Performance Músicas já no Redux store não disparam nova query ao banco carregarMusica — verificação prévia no store 🟢
Segurança Nenhum dado do catálogo é enviado externamente (somente-leitura local) Ausência de POST/PUT para entidades de música 🟢
Usabilidade Snippet do trecho encontrado é limitado por token para evitar overflow MusicasRepository — constante TOTAL_TOKENS 🟢

Critérios de Aceitação

Dado que o usuário está na tela de músicas sem filtros
Quando nenhum termo é digitado
Então a lista de músicas é exibida em ordem alfabética por título

Dado que o usuário digitou "ave maria" na busca
Quando a query FTS5 é executada
Então músicas com "Avé Maria" no título ou letra são retornadas ordenadas por relevância bm25

Dado que o usuário digitou "23" na busca com o livro "Canto Eucarístico" selecionado
Quando a busca é executada
Então a música com índice 23 naquele livro é retornada

Dado que o usuário está visualizando a letra de uma música
Quando a tela fica inativa por mais de 30 segundos
Então a tela não é bloqueada (Keep Awake ativo)

Dado que o usuário favoritou uma música
Quando o app é reiniciado
Então a música aparece na lista de favoritos (persistência SQLite confirmada)

Dado que o usuário acessou a letra de uma música
Quando a tela de letra é carregada
Então a música é adicionada ao repertório "Visto recentemente" de forma assíncrona sem bloquear a UI

Dado que o usuário toca em "Relatar erro"
Quando o formulário abre
Então os campos id_musica, titulo e inicio_da_letra estão pré-preenchidos no Airtable form

Dado que o termo de busca não produz resultados FTS5
Quando a query é executada
Então uma tela de estado vazio é exibida ao usuário

Prioridade (MoSCoW)

Requisito MoSCoW Justificativa
Busca textual FTS5 (RF-02) Must Caminho crítico — função principal do app
Listagem paginada (RF-01) Must Base de toda a navegação de músicas
Visualizar letra (RF-04) Must Razão de ser do produto
Filtro por livro (RF-05) Must Maioria dos usuários usa com livro físico em mãos
Favoritar música (RF-07) Must Fundamental para uso recorrente
Histórico "Visto recentemente" (RF-08) Must Repertório padrão id=2, criado na migration v8
Keep Awake (RF-09) Should Importante para UX, mas não bloqueia uso sem ele
Múltiplos YouTube (RF-10) Should Aprimoramento sobre campo deprecated
Filtro por rótulo (RF-06) Should Relevante para contexto litúrgico, não crítico para busca básica
Configuração adaptativa (RF-13) Should Melhora UX no tablet
Links CifraClub/Partitura (RF-11) Could Recursos secundários, presença condicional
Relatar erro (RF-12) Could Feedback de qualidade; não afeta funcionalidade principal

Rastreabilidade de Código

Arquivo Função / Classe Cobertura
src/model/Musica.ts InformacoesDetalhadasMusica 🟢
src/model/IndiceMusica.ts IndiceMusica 🟢
src/model/rotulo/CategoriaRotulos.ts Dicionário de rótulos (8 categorias) 🟢
src/repository/musicas/MusicasRepository.ts findAllBy, findById, BuscaStrategies 🟢
src/repository/musicas/MusicaConfiguration.ts TOTAL_CARACTERES, TOTAL_TOKENS 🟢
src/service/MusicaService.ts relatarErro, marcarAsVisualizada 🟢
src/store/Musicas/Musicas.action.ts carregarMusica, setFavorita 🟢
src/store/Musicas/Musicas.reducer.ts EntityAdapter, upsertOne 🟢