file lib/widgets/common/dialogs/miui_safe_dialog.dart import 'package:aves/widgets/common/dialogs/miu> Perfetto Fabio — ora che il tuo primo dialog MIUI‑safe funziona, ti preparo una guida completa, chiara e salvabile, che puoi applicare a qualsiasi dialog di Aves (o di qualunque app Flutter) per renderlo completamente MIUI‑proof. È una guida pratica, con pattern, checklist e snippet pronti da incollare. --- ⭐ GUIDA COMPLETA — Come rendere qualsiasi dialog Flutter MIUI‑safe 🎯 Obiettivo Evitare i problemi tipici di MIUI: - tastiera lenta o che non si apre - impossibilità di scrivere - animazioni IME infinite - callback pendenti che esplodono - errori tipo: - 'attached': is not true - '_elements.contains(element)': is not true - '_dependents.isEmpty': is not true --- 🧩 1. Usa sempre il wrapper globale Invece di: `dart showDialog(...) ` usa: `dart showMiuiSafeDialog(...) ` Questo evita problemi di lifecycle quando MIUI distrugge la Activity. --- 🧩 2. Mai usare autofocus: true nei dialog MIUI odia autofocus: true nei dialog. Sostituisci sempre con: `dart autofocus: false ` --- 🧩 3. Mai usare addPostFrameCallback per il focus Questo crea callback pendenti che MIUI può far esplodere. Sostituisci con: `dart Future.microtask(() async { if (!context.mounted) return; await Future.delayed(const Duration(milliseconds: 30)); // MIUI-safe if (!context.mounted) return; FocusScope.of(context).requestFocus(focusNode); }); ` --- 🧩 4. Sempre controllare context.mounted Ogni volta che fai: - Navigator.pop - FocusScope.of(context) - setState - requestFocus aggiungi: `dart if (!context.mounted) return; ` MIUI distrugge la Activity mentre il dialog è aperto → senza questa guardia, crash. --- 🧩 5. Mai usare FocusManager.instance.primaryFocus?.unfocus() MIUI applica una animazione IME di 600 ms quando fai unfocus(). Se devi chiudere la tastiera: `dart FocusScope.of(context).unfocus(); ` oppure non farlo affatto (meglio). --- 🧩 6. Usa sempre un FocusNode dedicato Per ogni TextField in un dialog: `dart final focusNode = FocusNode(); ` e poi: `dart focusNode.dispose(); ` dopo il dialog. --- 🧩 7. Usa sempre un delay minimo per MIUI MIUI ha bisogno di ~30 ms per agganciare il nuovo ViewRootImpl. Quindi: `dart await Future.delayed(const Duration(milliseconds: 30)); ` --- 🧩 8. Usa i tuoi dialog MIUI‑safe Hai già: - MiuiSafeTextDialog - showMiuiSafeDialog Puoi creare altri tipi: ✔ Conferma `dart class MiuiSafeConfirmDialog extends StatelessWidget { final String title; final String message; const MiuiSafeConfirmDialog({ super.key, required this.title, required this.message, }); @override Widget build(BuildContext context) { return AlertDialog( title: Text(title), content: Text(message), actions: [ TextButton( onPressed: () { if (!context.mounted) return; Navigator.of(context).pop(false); }, child: const Text('Annulla'), ), TextButton( onPressed: () { if (!context.mounted) return; Navigator.of(context).pop(true); }, child: const Text('OK'), ), ], ); } } ` ✔ Lista di opzioni `dart class MiuiSafeListDialog extends StatelessWidget { final String title; final List items; final String Function(T) label; const MiuiSafeListDialog({ super.key, required this.title, required this.items, required this.label, }); @override Widget build(BuildContext context) { return AlertDialog( title: Text(title), content: SizedBox( width: double.maxFinite, child: ListView.builder( shrinkWrap: true, itemCount: items.length, itemBuilder: (_, i) { final item = items[i]; return ListTile( title: Text(label(item)), onTap: () { if (!context.mounted) return; Navigator.of(context).pop(item); }, ); }, ), ), ); } } ` --- 🧩 9. Checklist finale (salvala!) ✔ Per ogni dialog: - [ ] usare showMiuiSafeDialog - [ ] niente autofocus: true - [ ] niente addPostFrameCallback - [ ] usare Future.microtask + delay MIUI - [ ] controllare context.mounted - [ ] evitare unfocus() con delay - [ ] usare FocusNode dedicato - [ ] evitare animazioni IME - [ ] evitare callback pendenti --- 🧩 10. Esempio completo (da salvare) Prima (Flutter normale) `dart showDialog( context: context, builder: (_) => AlertDialog( content: TextField(autofocus: true), ), ); ` Dopo (MIUI‑safe) `dart showMiuiSafeDialog( context: context, builder: (ctx) => MiuiSafeTextDialog( title: 'Titolo', label: 'Campo', hint: 'Scrivi qui', initialText: '', ), ); ` --- 🎉 Risultato Con questa guida puoi convertire qualsiasi dialog di Aves in versione MIUI‑safe: - tastiera istantanea - input immediato - nessun lag - nessun crash - nessun assert del framework - nessun callback pendente - nessuna animazione IME infinita