changed version check
All checks were successful
Build and Release FLUX (Multi-Platform) / build-android (push) Successful in 1m33s
Build and Release FLUX (Multi-Platform) / build-web (push) Successful in 1m4s
Build and Release FLUX (Multi-Platform) / build-windows (push) Successful in 6m14s

This commit is contained in:
2026-06-04 14:21:27 +02:00
parent 5ce0110197
commit 7ea0e2ac10
3 changed files with 95 additions and 20 deletions

View File

@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
@@ -47,6 +48,7 @@ import 'package:flux/features/master_data/store/data/store_repository.dart';
import 'package:flux/features/settings/ui/settings.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:universal_html/html.dart' as html;
String? initialRecoveryFragment;
void main() async {
@@ -304,21 +306,71 @@ class GlobalUpdateChecker extends StatefulWidget {
State<GlobalUpdateChecker> createState() => _GlobalUpdateCheckerState();
}
class _GlobalUpdateCheckerState extends State<GlobalUpdateChecker> {
class _GlobalUpdateCheckerState extends State<GlobalUpdateChecker>
with WidgetsBindingObserver {
bool _mustUpdate = false;
String? _updateUrl;
StreamSubscription? _versionSubscription;
@override
void initState() {
super.initState();
_checkVersionAndBlock();
// 🥷 1. Registriamo questo widget per ascoltare i cicli vitali dell'app
WidgetsBinding.instance.addObserver(this);
_startRealtimeVersionCheck();
}
Future<void> _checkVersionAndBlock() async {
@override
void dispose() {
// 🥷 2. Rimuoviamo l'observer quando il widget muore (mai, in questo caso, ma è buona norma)
WidgetsBinding.instance.removeObserver(this);
_stopRealtimeVersionCheck();
super.dispose();
}
// 🥷 3. IL VERO GESTORE DEL CICLO VITALE
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed) {
// L'app è tornata attiva: riaccendiamo il radar
_startRealtimeVersionCheck();
} else if (state == AppLifecycleState.paused ||
state == AppLifecycleState.hidden) {
// L'app è andata in background: spegniamo il socket per evitare crash
_stopRealtimeVersionCheck();
}
}
void _startRealtimeVersionCheck() {
// Sicurezza: cancelliamo eventuali vecchi abbonamenti rimasti appesi
_stopRealtimeVersionCheck();
// Facciamo un check immediato non appena rientriamo in app
_checkVersion();
// Riapriamo il rubinetto di Supabase
_versionSubscription = GetIt.I<SupabaseClient>()
.from(
'app_versions',
) // <-- Sostituisci col nome reale della tua tabella
.stream(primaryKey: ['id'])
.listen((_) {
_checkVersion();
});
}
void _stopRealtimeVersionCheck() {
// Chiudiamo gentilmente il socket
_versionSubscription?.cancel();
_versionSubscription = null;
}
Future<void> _checkVersion() async {
final updateUrl = await VersionCheckService().checkForceUpdate();
if (updateUrl != null && mounted) {
// Invece di aprire un dialog, cambiamo lo stato e attiviamo lo "Scudo"
setState(() {
_mustUpdate = true;
_updateUrl = updateUrl;
@@ -328,21 +380,15 @@ class _GlobalUpdateCheckerState extends State<GlobalUpdateChecker> {
@override
Widget build(BuildContext context) {
// 1. Se l'app è aggiornata, mostriamo solo l'app normale
if (!_mustUpdate) return widget.child;
// 2. Se l'app è vecchia, sovrapponiamo il blocco con uno Stack
return Stack(
children: [
// L'app sotto continua ad esistere, ma è inaccessibile
widget.child,
// IL BLOCCO INVALICABILE SOPRA A TUTTO
Positioned.fill(
child: Container(
color: Colors.black.withValues(alpha: 0.85), // Sfondo oscurante
color: Colors.black.withValues(alpha: 0.85),
child: Center(
// Usiamo Material per ereditare correttamente temi, font e colori
child: Material(
color: Colors.transparent,
child: Container(
@@ -386,7 +432,7 @@ class _GlobalUpdateCheckerState extends State<GlobalUpdateChecker> {
const SizedBox(height: 16),
Text(
kIsWeb
? "È stata rilasciata una nuova versione dell'applicazione. Ricarica la pagina per continuare."
? "È stata rilasciata una nuova versione dell'applicazione. Ricarica la pagina per scaricare il nuovo codice."
: "Per continuare ad utilizzare l'applicazione è necessario scaricare e installare l'ultimo aggiornamento.",
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 16),
@@ -399,18 +445,14 @@ class _GlobalUpdateCheckerState extends State<GlobalUpdateChecker> {
style: FilledButton.styleFrom(
minimumSize: const Size(double.infinity, 50),
),
onPressed: () async {
// Trick cross-platform per fare il reload
await launchUrl(
Uri.parse(Uri.base.toString()),
webOnlyWindowName: '_self',
);
onPressed: () {
// Hard reload aggirando la cache!
html.window.location.reload();
},
)
else
FilledButton.icon(
icon: const Icon(Icons.download),
label: const Text("SCARICA AGGIORNAMENTO"),
style: FilledButton.styleFrom(
minimumSize: const Size(double.infinity, 50),