Sem targetSdkVersion no manifest, o AGP usou minSdk (26) como alvo:
o instalador do Android 16 (One UI 8) bloqueia o APK como 'versão
antiga do Android'. Restore targetSdk=35 + versionCode 6 / 0.3.1.
Verificado em emulador Android 16 (API 36, Pixel 6): install sem
bloqueio, boot limpo, fluxo config -> lista -> status/busca/empty state.
- Edge-to-edge (enableEdgeToEdge) com Scaffold/insets em todas as telas
- Compose BOM 2024.12 -> 2025.06; tipografia e tema com dynamic color
- SyncBanner colorido removido -> SyncStatusRow compacto com chips M3
acionáveis (sync agora / abrir config / erro em errorContainer)
- Lista: busca por título/conteúdo/tag (filterNotes testado),
pull-to-refresh, animateItem, contentType, estado vazio com CTA
- Ícones no lugar de emoji (pasta, presença, exclusão, aviso)
- Editor: chip de presença acessível; imports limpos
- Teste unitário de busca (NoteSearchTest)
- versionCode 5 / versionName 0.3.0
- SyncEngine: CancellationException volta a propagar (não vira erro falso)
- SyncWorker: Failed (4xx/5xx) agora é failure, só NetworkDown retenta
- ApiClient: métodos suspend com delay() em vez de Thread.sleep
- SseClient: cancelamento fecha o socket; parse tolera 'data:' sem espaço
- Room v3: migração real 2->3 (índice único outbox) sem apagar a fila
- versionCode 4 / versionName 0.2.2
- Botão 🗑 no card da lista e na barra do editor; AlertDialog de confirmação
explicando o efeito (remoto sobe na sync; local-only some direto)
- Exclusões já eram enfileiradas (pendingDelete + op delete) e o engine já
tratava 404; propagação via SSE 'deleted' para outras sessões
- versionCode 3 / versionName 0.2.1; README atualizado
- Testado no emulador: delete pela lista → servidor 0 notas; delete pelo
editor → idem, com volta à lista; pull de nota da Web e exclusão seguinte ok
- Room (notes/outbox/categories/meta): edição 100% local, fila FIFO de mutações
- SyncEngine bidirecional: push (create/update com base_hash/delete, rekey de id
local→servidor) + pull (categorias, notas divergentes, exclusões remotas)
- Conflito 409: servidor vence a nota + texto local preservado em cópia
"Título (conflito)" enfileirada como create — nada perdido, sem relógios
- WorkManager: periódico 1h (rede + backoff exponencial), runNow único REPLACE
em gatilhos (pós-save, rede restabelecida, boot, config, botão manual)
- OkHttp com timeout/retry em IOException; kotlinx.serialization; DataStore
- UI Compose: tela Servidor (URL+token+teste), Lista com banner de status
(Offline/Sincronizando/Sincronizado/Erro/401 + pendências + conflitos),
Editor com autosave por ociosidade (10 s) e categorias multi-seleção
- Build validado: assembleDebug (AGP 8.7.3/Kotlin 2.0.21/SDK 35, JDK 21) —
app-debug.apk 17,6 MB; gradle-wrapper.jar fora do commit (regenerável com
`gradle wrapper`, documentado no README)