Eventos
Como no InkShelf não existe uma máquina de estados formal, também não existe um barramento de eventos central. A interação entre a interface e os ViewModels é, na esmagadora maioria dos casos, chamada direta de função, não emissão de eventos tipados.
O padrão dominante: callbacks, não eventos
Uma Composable chama diretamente um método do ViewModel (onClick = { viewModel.markAsRead(id) }) ou uma lambda repassada por um objeto de configuração da tela (o padrão Cfg usado nas telas de Configurações, que carrega dezenas de callbacks como toast: (String) -> Unit, onRescan: () -> Unit, etc.). Não há um objeto Event intermediário sendo despachado e escutado — é uma chamada de função comum, sem indireção.
A única exceção: mensagens de exportação
O único lugar do app que usa um fluxo de eventos de fato — um SharedFlow desacoplado do estado atual da tela, para não ser reemitido numa recomposição ou rotação de tela — é a confirmação de exportação de página no leitor: sucesso ou falha da exportação emite uma mensagem única, consumida uma vez pela interface para mostrar um aviso rápido. Esse padrão não se repete em nenhuma outra funcionalidade do app; em todo o resto, mensagens de confirmação usam a mesma função de callback direta (toast) descrita acima.
Eventos que vêm de fora do app
Os eventos reais que o InkShelf precisa tratar como coisas que "acontecem para ele", em vez de ações do próprio usuário dentro da UI, vêm do sistema operacional:
- Abertura externa por
ACTION_VIEW: outro app (gerenciador de arquivos, navegador) pede para abrir um arquivo suportado diretamente no leitor do InkShelf. - Toque em notificação: uma notificação de retomar leitura ou sugestão de próximo arquivo (ver Notificações) carrega o ID do arquivo a abrir; tocar nela relança a Activity com esse ID, que é interpretado como um pedido de navegação direta para o leitor.
- Disparo de worker do WorkManager: as notificações agendadas em si são eventos de sistema entregues em segundo plano, fora de qualquer interação do usuário — ver Notificações para o ciclo completo de agendamento e dos checks feitos no momento do disparo.
- Resultado de uma chamada de rede a um servidor remoto: o resultado de testar conexão, sincronizar uma fonte Komga/Kavita ou tocar em "Reconectar" (ver Fontes Remotas) chega de forma assíncrona e imprevisível (o servidor pode estar fora do ar, lento, ou responder um erro) — mesmo padrão de callback direto do resto do app (o resultado vira estado observado via
StateFlow/Toast), não um evento tipado à parte.
Esses quatro casos são os únicos pontos de entrada onde o app reage a algo que não foi ele mesmo que iniciou.