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 singularYouTubeestá 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ítuloeiní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 aTOTAL_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 |
🟢 |