Ir para o conteúdo

Cobertura de renderizadores (Qt vs Compose)

O tempestroid tem um reconciliador e dois renderizadores-folha: o Qt (simulador desktop) e o Compose (dispositivo Android, Kotlin). Esta página é a matriz de qual widget cada renderizador trata — a referência para saber o que roda no aparelho além do simulador.

O que cada coluna significa

  • Qt (simulador) — o widget tem um caminho de render no renderizador Qt (tempestroid/renderers/qt/).
  • Compose (device) — o renderizador Kotlin (android-host/.../TempestRenderer.kt) tem um case explícito que monta um Composable real para o type do nó (não cai no fallback Box/Popup).
  • Esta matriz reflete cobertura no nível de código (existe um tratador). A verificação on-device por widget (screenshot de cada um no aparelho) é feita nas rodadas de device-verify das fases E e segue como trabalho contínuo — onde não foi exercida, está sinalizado.

Resumo

Todo widget primitivo exportado tem um tratador nos dois renderizadores. O renderizador Compose tem 62 cases primitivos + 7 de overlay; qualquer type sem case cai num Box/Popup forward-compat (nunca quebra). Os componentes compostos (tempestroid/components/) são rebaixados a primitivos no Python (Component.render) antes da serialização — então nunca chegam ao Kotlin: renderizam via seus filhos primitivos nos dois lados.

Layout

Widget Qt (simulador) Compose (device) Notas
Column
Row
Container No Compose cai no Box forward-compat (estilo + filhos).
Stack Z-order; position=ABSOLUTE ancora por insets.
SafeArea Compose inseta contra WindowInsets.safeDrawing.
Wrap Quebra de linha fixada na conformância (flex_wrap).
AspectRatio
PageView Emite PageChangeEvent.
ScrollView
KeyboardAvoidingView

Texto, ação e indicadores

Widget Qt (simulador) Compose (device) Notas
Text
Button
Icon Ícones Material nomeados.
Image Compose via Coil.
ProgressBar
Spinner

Inputs e formulários

Widget Qt (simulador) Compose (device) Notas
Input
TextArea
Checkbox
Switch
Slider
RangeSlider Qt: dois QSlider; Compose: M3 RangeSlider.
Dropdown / Select
TimePicker Qt: spinner inline; Compose: dialog M3.
DatePicker
FilePicker
Autocomplete
PinInput
MaskedInput
FormField Validação roda no Python; renderer só desenha o erro.
Form

Listas virtualizadas

Widget Qt (simulador) Compose (device) Notas
LazyColumn Janela materializada pela app; veja divergências.
LazyRow
LazyGrid
SectionList Cabeçalho fixo: QLabel flutuante (Qt) vs stickyHeader (Compose).
RefreshControl Qt: prop refreshing (sem gesto de puxar); Compose: PullToRefreshBox.
Widget Qt (simulador) Compose (device) Notas
Navigator Qt: QStackedWidget + QPropertyAnimation; Compose: AnimatedContent.
TabView
TabBar
RouteDrawer Compose: ModalDrawer.

Overlays e feedback

Widget Qt (simulador) Compose (device) Notas
Dialog Compose: AlertDialog M3.
BottomSheet Compose: ModalBottomSheet.
ActionSheet
Toast
Menu Compose: DropdownMenu.
Popover
Tooltip

Animação

Widget Qt (simulador) Compose (device) Notas
Animated Clock de frames cruza a ponte (FRAME_TOKEN).
AnimatedList
Shimmer
Skeleton
Hero Transição compartilhada entre telas.

Gestos

Widget Qt (simulador) Compose (device) Notas
GestureDetector on_tap / on_double_tap / on_long_press / on_swipe.
PanHandler
ScaleHandler Pinça/zoom.
DoubleTapHandler
Draggable
DragTarget
Dismissible Swipe-to-delete.
ReorderableList
InteractiveViewer

Mídia e gráficos

Widget Qt (simulador) Compose (device) Notas
Canvas Lista de comandos JSON idêntica (conformância).
Svg
Blur / BackdropFilter
ClipPath
VideoPlayer Compose via AndroidView.
WebView Compose via AndroidView.
CameraPreview ⚠️ placeholder ✅ device Qt mostra placeholder sinalizado; câmera real só no device.
QrScanner ⚠️ placeholder ✅ device idem — leitura de QR só no device.
MapView ⚠️ placeholder ✅ device idem — mapa real só no device.

Componentes compostos

Tudo em tempestroid/components/ (AppBar, Scaffold, NavBar, Sidebar, Footer, Header, Card, Drawer, Calendar, Clock, componentes BR de formulário, etc.) é rebaixado a primitivos no Python por Component.render antes do diff. O reconciliador nunca serializa um tipo Component para o aparelho — o Kotlin só vê os filhos primitivos. Logo os componentes herdam a cobertura dos primitivos que emitem, idêntica nos dois renderizadores.

Divergências documentadas

Os dois renderizadores casam em comportamento e payload de evento, mas usam mecanismos nativos distintos. As divergências fixadas pela suíte de conformidade (fase D) e descritas no CLAUDE.md:

  • Listas: a área de scroll Qt cobre só a janela materializada (sem extensão virtual reservada); o LazyColumn do Compose reporta layoutInfo contra o itemCount total.
  • Overlays: Qt usa QDialog/QMenu/QTimer; Compose usa Material3 (AlertDialog/ModalBottomSheet/DropdownMenu) que gerenciam o próprio scrim e WindowInsets.safeDrawing.
  • Navegação: Qt anima com QPropertyAnimation; Compose com AnimatedContent/ModalDrawer. O botão voltar do Android é o caminho device (vs Esc no simulador).
  • Mídia device-only: câmera, QR e mapa são placeholders sinalizados no Qt e reais só no aparelho.

Fonte da verdade

A coluna Compose (device) é derivada diretamente do when (node.type) em android-host/app/src/main/java/.../TempestRenderer.kt (dispatch primário + de overlay). Ao adicionar um widget novo, garanta um case lá e uma entrada nesta matriz.