diff --git a/example/lib/main.dart b/example/lib/main.dart index 15f09c2..179c3bc 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -85,7 +85,7 @@ class _HomePageState extends State { supportedMethods: [AppUpgradeMethod.browser, AppUpgradeMethod.inApp, AppUpgradeMethod.market], ); }, - showNoUpdateToast: true, + showNoUpdateToast: false, // 禁用"已是最新版本"的提示 autoDownload: false, autoInstall: true, ); @@ -139,7 +139,7 @@ class _HomePageState extends State { downloadUrl: 'https://example.com/app.apk', ); }, - showNoUpdateToast: true, + showNoUpdateToast: false, // 禁用"已是最新版本"的提示 autoDownload: false, autoInstall: false, ); diff --git a/lib/app_upgrade_simple.dart b/lib/app_upgrade_simple.dart index cdc905f..36d6bba 100644 --- a/lib/app_upgrade_simple.dart +++ b/lib/app_upgrade_simple.dart @@ -1,12 +1,12 @@ import 'dart:async'; import 'dart:io'; +import 'package:app_upgrade_plugin/core/upgrade_utils.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import 'app_upgrade_plugin_platform_interface.dart'; import 'core/permission_helper.dart'; -import 'core/upgrade_utils.dart'; import 'models/app_upgrade_method.dart'; import 'models/app_upgrade_version.dart'; import 'models/upgrade_info.dart'; @@ -217,11 +217,12 @@ class AppUpgradeSimple { /// - false: 下载完成后需要用户手动触发安装(默认) /// - null: 使用 [config] 或全局配置的 [UpgradeConfig.autoInstall] /// - 注意:仅在 [autoDownload] 为 true 时生效 - /// - [onComplete] (可选) 完成回调函数 + /// - [onComplete] (可选) 完成回调函数,接收一个 bool 参数表示是否更新成功 + /// - true: 更新成功或已是最新版本 + /// - false: 用户取消更新或更新失败 /// - 在以下情况会被调用: /// - 检查完成(无论是否有更新) - /// - 检查失败 - /// - 用户关闭升级对话框 + /// - 用户完成更新或关闭升级对话框 /// - [config] (可选) 升级配置对象 [UpgradeConfig] /// - 如果提供,会覆盖全局配置和单个参数设置 /// - 如果为 null,使用全局配置 [UpgradeConfig] @@ -239,8 +240,8 @@ class AppUpgradeSimple { /// showNoUpdateToast: true, /// autoDownload: false, /// autoInstall: false, - /// onComplete: () { - /// print('检查更新完成'); + /// onComplete: (success) { + /// print('检查更新完成,结果: $success'); /// }, /// ); /// ``` @@ -256,7 +257,7 @@ class AppUpgradeSimple { bool? showNoUpdateToast, bool? autoDownload, bool? autoInstall, - VoidCallback? onComplete, + BoolCallback? onComplete, UpgradeConfig? config, }) async { // 使用传入的配置或默认配置 @@ -270,11 +271,11 @@ class AppUpgradeSimple { // 1. 获取服务器版本信息 final serverInfo = await future(); if (serverInfo == null) { - // 获取失败或无数据,视作无更新 + // 获取失败或无数据,视作无更新(已是最新) if (effectiveConfig.enableDebugLog) { debugPrint('🔍 检查更新结果: 未返回版本信息'); } - onComplete?.call(); + onComplete?.call(true); return; } @@ -336,7 +337,7 @@ class AppUpgradeSimple { if (finalShowNoUpdateToast && context.mounted) { _showToast('已是最新版本', context, effectiveConfig); } - onComplete?.call(); + onComplete?.call(true); return; } @@ -354,7 +355,7 @@ class AppUpgradeSimple { if (context.mounted) { _showToast('检查更新遇到问题', context, effectiveConfig); } - onComplete?.call(); + onComplete?.call(true); } } @@ -490,7 +491,7 @@ class AppUpgradeSimple { required UpgradeInfo info, required bool autoDownload, required bool autoInstall, - VoidCallback? onComplete, + BoolCallback? onComplete, UpgradeConfig? config, }) { final effectiveConfig = config ?? _config; @@ -639,7 +640,7 @@ mixin _UpgradeDialogLogic on State { UpgradeInfo get info; void Function(String) get showToast; - VoidCallback? get onComplete; + BoolCallback? get onComplete; bool get autoDownload; bool get autoInstall; UpgradeConfig get config; @@ -904,7 +905,7 @@ mixin _UpgradeDialogLogic on State { if (mounted && Navigator.canPop(context)) { Navigator.of(context).pop(); } - onComplete?.call(); + onComplete?.call(true); }); } @@ -1027,24 +1028,20 @@ mixin _UpgradeDialogLogic on State { colorScheme: colorScheme, ), ), - ], - ), - if (info.apkSize != null) ...[ - const SizedBox(height: 8), - Row( - children: [ + if (info.apkSize != null) ...[ + const SizedBox(width: 8), Expanded( child: _buildInfoChip( context, icon: Icons.file_download, - label: '大小', + label: '新版体积', value: formatBytes(info.apkSize!), colorScheme: colorScheme, ), ), ], - ), - ], + ], + ), ], ), ); @@ -1058,7 +1055,7 @@ mixin _UpgradeDialogLogic on State { required ColorScheme colorScheme, }) { return Container( - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), decoration: BoxDecoration( color: colorScheme.surface, borderRadius: BorderRadius.circular(8), @@ -1087,7 +1084,7 @@ mixin _UpgradeDialogLogic on State { ), ], ), - const SizedBox(height: 2), + const SizedBox(height: 4), Text( value, style: TextStyle( @@ -1127,10 +1124,10 @@ mixin _UpgradeDialogLogic on State { ), ], ), - const SizedBox(height: 12), + const SizedBox(height: 6), Container( width: double.infinity, - constraints: const BoxConstraints(maxHeight: 200), + constraints: const BoxConstraints(maxHeight: 300), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest.withOpacity(0.3), @@ -1657,7 +1654,7 @@ mixin _UpgradeDialogLogic on State { if (info.appStoreUrl != null) { _plugin.goToAppStore(info.appStoreUrl!, context: context); // 移除关闭弹窗代码,始终不关闭 - onComplete?.call(); + onComplete?.call(true); } else { showToast('App Store URL is not available.'); } @@ -1731,7 +1728,7 @@ mixin _UpgradeDialogLogic on State { Future _handleMarketAction() async { if (!mounted) return; await _performMarketAction(); - onComplete?.call(); + onComplete?.call(true); // 移除关闭弹窗代码 } @@ -1768,15 +1765,22 @@ mixin _UpgradeDialogLogic on State { child: Stack( alignment: Alignment.center, children: [ - const Text('选择更新方式', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), - if (!info.isForceUpdate) - Positioned( - right: -12, - child: IconButton( - icon: const Icon(Icons.close), - onPressed: () => Navigator.of(ctx).pop(), - ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Text('选择更新方式', + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold))), + ], + ), + Positioned( + right: -12, + child: IconButton( + icon: const Icon(Icons.close), + onPressed: () => Navigator.of(ctx).pop(), ), + ), ], ), ), @@ -1802,25 +1806,24 @@ mixin _UpgradeDialogLogic on State { onTap: () => Navigator.of(ctx).pop(AppUpgradeMethod.browser), ), const Divider(height: 24), - if (!info.isForceUpdate) - SizedBox( - width: double.infinity, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 12), - backgroundColor: Colors.white, - foregroundColor: Theme.of(context).textTheme.bodyLarge?.color, - elevation: 2, - shadowColor: Colors.grey.withOpacity(0.5), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - side: BorderSide(color: Colors.grey.shade300), - ), + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + padding: const EdgeInsets.symmetric(vertical: 12), + backgroundColor: Colors.white, + foregroundColor: Theme.of(context).textTheme.bodyLarge?.color, + elevation: 2, + shadowColor: Colors.grey.withOpacity(0.5), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: BorderSide(color: Colors.grey.shade300), ), - onPressed: () => Navigator.of(ctx).pop(), - child: const Text('取消', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)), ), + onPressed: () => Navigator.of(ctx).pop(), + child: const Text('取消', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)), ), + ), ], ), ), @@ -1831,7 +1834,7 @@ mixin _UpgradeDialogLogic on State { // 不再关闭弹窗,即使用户选择了更新方式 if (choice == AppUpgradeMethod.market) { await _performMarketAction(); - onComplete?.call(); + onComplete?.call(true); return; } @@ -1850,7 +1853,7 @@ class _SimpleUpgradeDialog extends StatefulWidget { final UpgradeInfo info; final bool autoDownload; final bool autoInstall; - final VoidCallback? onComplete; + final BoolCallback? onComplete; final void Function(String) showToast; final UpgradeConfig config; @@ -1873,7 +1876,7 @@ class _SimpleUpgradeDialogState extends State<_SimpleUpgradeDialog> with _Upgrad @override void Function(String) get showToast => widget.showToast; @override - VoidCallback? get onComplete => widget.onComplete; + BoolCallback? get onComplete => widget.onComplete; @override bool get autoDownload => widget.autoDownload; @override @@ -1962,7 +1965,7 @@ class _SimpleUpgradeDialogState extends State<_SimpleUpgradeDialog> with _Upgrad TextButton( onPressed: () { Navigator.of(context).pop(); - widget.onComplete?.call(); + widget.onComplete?.call(false); }, child: const Text('稍后更新'), ), @@ -2001,7 +2004,7 @@ class _ForceUpgradeDialogState extends State<_ForceUpgradeDialog> with _UpgradeD void Function(String) get showToast => (message) => AppUpgradeSimple.instance._showToast(message, context, widget.config); @override - VoidCallback? get onComplete => null; + BoolCallback? get onComplete => null; @override bool get autoDownload => false; @override @@ -2040,7 +2043,7 @@ class _ForceUpgradeDialogState extends State<_ForceUpgradeDialog> with _UpgradeD child: Container( width: 320, constraints: const BoxConstraints( - maxHeight: 600, + maxHeight: 700, ), child: Column( mainAxisSize: MainAxisSize.min, @@ -2168,3 +2171,5 @@ class _ToastWidget extends StatelessWidget { ); } } + +typedef BoolCallback = void Function(bool success);