Skip to content

Máquinas de Estado — canta-igreja

Gerado pelo Detective (Reversa) em 2026-05-11


1. Autenticação do Usuário

Entidade: Auth + UsuarioLogadoRepository

stateDiagram-v2
    [*] --> Anonimo : App abre sem credenciais

    Anonimo --> Autenticando : Usuário toca "compartilhar"/"folheto"
    Autenticando --> Autenticado : OAuth PKCE bem-sucedido + POST /auth OK
    Autenticando --> Anonimo : Usuário cancela ou erro de rede

    Autenticado --> RefreshEmAndamento : Token expira em ≤ 1 min
    RefreshEmAndamento --> Autenticado : refresh() bem-sucedido
    RefreshEmAndamento --> Anonimo : refresh() falha (token revogado)

    Autenticado --> Anonimo : logout() — keychain + MMKV limpos

    note right of Autenticado
        idToken disponível
        UsuarioLogado no MMKV
    end note

    note right of Anonimo
        Todas as funcionalidades de
        leitura disponíveis normalmente
    end note

Gatilhos de transição: | Transição | Gatilho | |-----------|---------| | Anonimo → Autenticando | Usuário toca compartilhar/gerar folheto | | Autenticando → Autenticado | Auth.autenticar() completa com sucesso | | Autenticado → RefreshEmAndamento | (expirationDate - 1min) < agora | | Autenticado → Anonimo | Auth.logout() |


2. Download de Obra (Biblioteca)

Entidade: ObraService + BibliotecaRepository

stateDiagram-v2
    [*] --> Disponivel : Obra listada pela API

    Disponivel --> Baixando : Usuário toca "baixar"
    Baixando --> Baixando : downloadEmAndamento = true (mutex)

    Baixando --> Importando : Arquivo .db recebido no cache
    Importando --> Instalada : ATTACH → upsert → DETACH concluídos

    Baixando --> Erro : Falha de rede ou disco
    Importando --> Erro : Falha no ATTACH/upsert

    Erro --> Disponivel : Usuário retenta

    Instalada --> Desatualizada : API retorna crc32 diferente
    Desatualizada --> Baixando : Usuário toca "atualizar"

    note right of Baixando
        Apenas 1 download
        simultâneo permitido
    end note

Regra de mutex: ObraService.downloadEmAndamento — se true, tentativa de novo download lança exceção imediatamente.


3. Sincronização de Sugestões de Repertório

Entidade: BibliotecaSugestoesRepertorioRepository

stateDiagram-v2
    [*] --> Vazio : Primeira instalação

    Vazio --> Semeado : popularSugestoesIniciais() — cópia do asset repertorios.db
    Semeado --> Atualizado : importarSugestoes() — substituição total via ATTACH

    Atualizado --> Baixando : App detecta novo banco na API
    Baixando --> Atualizando : Arquivo .db baixado para cache
    Atualizando --> Atualizado : ATTACH → DELETE ALL → INSERT ALL → DETACH

    Baixando --> Atualizado : Falha no download — mantém versão atual

    note right of Semeado
        Funciona offline
        (banco embarcado no app)
    end note
    note right of Atualizando
        Substituição TOTAL —
        não incremental
    end note

4. Repertório — Ciclo de Vida

Entidade: Repertorio

stateDiagram-v2
    [*] --> Criado : createRepertorio()

    Criado --> EmEdicao : Usuário abre e adiciona/remove músicas
    EmEdicao --> Criado : Usuário fecha sem mais alterações

    Criado --> Compartilhado : CompartilharService.repertorio() — API sync
    Compartilhado --> Criado : Usuário edita após compartilhar (slug.corrente mantido)
    Compartilhado --> Compartilhado : Re-compartilhamento (slug.corrente atualizado)

    Criado --> Excluido : deactivateRepertorio() — soft-delete

    state Compartilhado {
        [*] --> SlugAtribuido : slug.referencia + slug.corrente definidos
        SlugAtribuido --> ReferenciaOriginal : slug.referencia ≠ slug.corrente (importado)
        SlugAtribuido --> CorrenteProprietario : slug.referencia = slug.corrente (próprio)
    }

    note right of Excluido
        data_exclusao preenchida
        Registro permanece no banco
    end note

5. Player YouTube

Entidade: YoutubePlayerView + usePlayerState + useLoopControl

stateDiagram-v2
    [*] --> Fechado

    Fechado --> FullScreen : Usuário abre música com vídeo
    FullScreen --> Paused : Usuário pausa
    Paused --> FullScreen : Usuário retoma

    FullScreen --> MiniPlayer : Usuário minimiza
    MiniPlayer --> FullScreen : Usuário expande

    FullScreen --> Fechado : Usuário fecha
    MiniPlayer --> Fechado : Usuário fecha no mini

    state FullScreen {
        [*] --> Reproduzindo
        Reproduzindo --> LoopAtivo : Usuário define início/fim do loop
        LoopAtivo --> Reproduzindo : Usuário desativa loop
        Reproduzindo --> VelocidadeAlterada : Usuário muda velocidade (0.5x–2x)
        VelocidadeAlterada --> Reproduzindo
    }

    state LoopAtivo {
        [*] --> Polling : setInterval 500ms
        Polling --> SeekToInicio : currentTime >= loopState.end
        SeekToInicio --> Polling
    }

6. Sugestão → Repertório (Conversão)

Entidade: SugestaoRepertorioRepertorio

stateDiagram-v2
    [*] --> SugestaoDisponivel : Sugestão listada por dia litúrgico

    SugestaoDisponivel --> SugestaoSelecionada : Usuário abre sugestão
    SugestaoSelecionada --> RepertorioCriado : Usuário toca "Usar sugestão"
    RepertorioCriado --> [*] : Navega para edição do repertório criado

    state RepertorioCriado {
        [*] --> IterandoItens
        IterandoItens --> ItemIgnorado : metadata.ignorar = true
        IterandoItens --> ItemAdicionado : id_musica + momento inseridos
        ItemIgnorado --> IterandoItens
        ItemAdicionado --> IterandoItens
    }

    note right of RepertorioCriado
        Métrica: repertorio_criado_por_sugestao
    end note