OTA Updates for adnroid app and web apk uploader

This commit is contained in:
2026-03-15 19:24:34 +08:00
parent 9bbaf67fef
commit 6fd3b66251
12 changed files with 1193 additions and 151 deletions
+55 -32
View File
@@ -615,46 +615,69 @@ class UpdateCheckWrapper extends StatefulWidget {
class _UpdateCheckWrapperState extends State<UpdateCheckWrapper> {
bool _done = false;
AppUpdateInfo? _info;
@override
void initState() {
super.initState();
_performCheck();
}
Future<AppUpdateInfo> _checkForUpdates() =>
AppUpdateService.instance.checkForUpdate();
Future<void> _performCheck() async {
try {
_info = await AppUpdateService.instance.checkForUpdate();
} catch (e) {
debugPrint('update check failed: $e');
}
if (mounted) {
setState(() => _done = true);
if (_info?.isUpdateAvailable == true) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
context: globalNavigatorKey.currentContext!,
barrierDismissible: !_info!.isForceUpdate,
builder: (_) => UpdateDialog(info: _info!),
);
});
Future<void> _handleUpdateComplete(AppUpdateInfo? info) async {
if (!mounted) return;
if (info?.isUpdateAvailable == true) {
// Keep the update-check screen visible while the dialog is shown.
// Use a safe context reference; fall back to the wrapper's own context.
final dialogContext = globalNavigatorKey.currentContext ?? context;
try {
await showDialog(
context: dialogContext,
barrierDismissible: !(info?.isForceUpdate ?? false),
builder: (_) => UpdateDialog(info: info!),
);
} catch (_) {
// If the dialog fails (rare), continue to the next screen.
}
}
if (!mounted) return;
setState(() {
_done = true;
});
}
@override
Widget build(BuildContext context) {
if (!_done) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: AppTheme.light(),
darkTheme: AppTheme.dark(),
themeMode: ThemeMode.system,
home: const UpdateCheckingScreen(),
);
}
return const NotificationBridge(child: TasqApp());
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: AppTheme.light(),
darkTheme: AppTheme.dark(),
themeMode: ThemeMode.system,
home: AnimatedSwitcher(
duration: const Duration(milliseconds: 420),
switchInCurve: Curves.easeOutCubic,
switchOutCurve: Curves.easeInCubic,
transitionBuilder: (child, animation) {
final curved = CurvedAnimation(
parent: animation,
curve: Curves.easeOutCubic,
reverseCurve: Curves.easeInCubic,
);
return FadeTransition(
opacity: curved,
child: ScaleTransition(
scale: Tween<double>(begin: 0.94, end: 1.0).animate(curved),
child: child,
),
);
},
child: kIsWeb
? const NotificationBridge(child: TasqApp())
: (_done
? const NotificationBridge(child: TasqApp())
: UpdateCheckingScreen(
checkForUpdates: _checkForUpdates,
onCompleted: _handleUpdateComplete,
)),
),
);
}
}