Files
wushu/lib/utils/force_guide_checker.dart
2026-03-30 02:35:31 +08:00

240 lines
7.7 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../config/app_config.dart';
import '../constants/app_constants.dart';
/// 时间: 2026-03-27
/// 功能: 强制引导页检查器
/// 介绍: 确保引导页一定会显示,如果没有显示则抛出异常并显示错误对话框
/// 最新变化: 新建强制检查机制
class ForceGuideChecker {
/// 强制检查引导页状态
/// 返回 true 表示需要显示引导页false 表示不需要
/// 如果检测到异常情况,会抛出 GuidePageException
static Future<GuideCheckResult> checkAndValidate(
SharedPreferences prefs,
) async {
try {
// 获取所有键
final allKeys = prefs.getKeys();
debugPrint('=== 强制引导页检查 ===');
debugPrint('所有配置项: $allKeys');
// 检查关键配置是否存在
final bool hasFirstLaunch = prefs.containsKey(AppConfig.keyFirstLaunch);
final bool hasAgreementAccepted =
prefs.containsKey(AppConfig.keyAgreementAccepted);
final bool hasAppVersion = prefs.containsKey(AppConfig.keyAppVersion);
debugPrint('hasFirstLaunch: $hasFirstLaunch');
debugPrint('hasAgreementAccepted: $hasAgreementAccepted');
debugPrint('hasAppVersion: $hasAppVersion');
// 获取状态值
final bool firstLaunch = prefs.getBool(AppConfig.keyFirstLaunch) ?? true;
final bool agreementAccepted =
prefs.getBool(AppConfig.keyAgreementAccepted) ?? false;
final int? savedVersion = prefs.getInt(AppConfig.keyAppVersion);
debugPrint('firstLaunch: $firstLaunch');
debugPrint('agreementAccepted: $agreementAccepted');
debugPrint('savedVersion: $savedVersion');
// 判断是否需要显示引导页
bool needGuide = false;
String reason = '';
// 情况1: 首次安装(没有版本号)
if (savedVersion == null) {
needGuide = true;
reason = '首次安装(无版本号)';
debugPrint('需要引导页: $reason');
}
// 情况2: firstLaunch 为 true
else if (firstLaunch) {
needGuide = true;
reason = '首次启动标志为 true';
debugPrint('需要引导页: $reason');
}
// 情况3: 未同意协议
else if (!agreementAccepted) {
needGuide = true;
reason = '未同意协议';
debugPrint('需要引导页: $reason');
}
// 情况4: 缺少关键配置
else if (!hasFirstLaunch || !hasAgreementAccepted) {
needGuide = true;
reason = '缺少关键配置项';
debugPrint('需要引导页: $reason');
} else {
debugPrint('不需要引导页,正常启动');
}
return GuideCheckResult(
needGuide: needGuide,
reason: reason,
firstLaunch: firstLaunch,
agreementAccepted: agreementAccepted,
savedVersion: savedVersion,
hasFirstLaunch: hasFirstLaunch,
hasAgreementAccepted: hasAgreementAccepted,
hasAppVersion: hasAppVersion,
allKeys: allKeys.toList(),
);
} catch (e) {
debugPrint('强制引导页检查异常: $e');
throw GuidePageException('引导页检查失败: $e');
}
}
/// 显示错误对话框
static void showErrorDialog(
BuildContext context,
GuideCheckResult result,
String errorMessage,
) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
title: Row(
children: [
Icon(Icons.error, color: Colors.red),
const SizedBox(width: 8),
const Text('引导页加载异常'),
],
),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'错误信息:',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(8),
),
child: Text(
errorMessage,
style: TextStyle(fontSize: 12, fontFamily: 'monospace'),
),
),
const SizedBox(height: 16),
Text(
'检测结果:',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
_buildInfoRow('需要引导页', result.needGuide ? '' : ''),
_buildInfoRow('原因', result.reason),
_buildInfoRow('firstLaunch', result.firstLaunch.toString()),
_buildInfoRow(
'agreementAccepted', result.agreementAccepted.toString()),
_buildInfoRow('savedVersion', result.savedVersion?.toString() ?? 'null'),
_buildInfoRow('hasFirstLaunch', result.hasFirstLaunch.toString()),
_buildInfoRow('hasAgreementAccepted',
result.hasAgreementAccepted.toString()),
_buildInfoRow('hasAppVersion', result.hasAppVersion.toString()),
const SizedBox(height: 8),
Text(
'所有配置项: ${result.allKeys}',
style: TextStyle(fontSize: 11, color: Colors.grey[600]),
),
],
),
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('关闭'),
),
ElevatedButton(
onPressed: () async {
// 清空所有配置并重启
final prefs = await SharedPreferences.getInstance();
await prefs.clear();
Navigator.of(context).pop();
},
style: ElevatedButton.styleFrom(
backgroundColor: AppConstants.primaryColor,
),
child: const Text('清空配置'),
),
],
),
);
}
static Widget _buildInfoRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 2),
child: Row(
children: [
SizedBox(
width: 120,
child: Text(
'$label:',
style: TextStyle(fontSize: 12, color: Colors.grey[700]),
),
),
Expanded(
child: Text(
value,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
),
),
],
),
);
}
}
/// 引导页检查结果
class GuideCheckResult {
final bool needGuide;
final String reason;
final bool firstLaunch;
final bool agreementAccepted;
final int? savedVersion;
final bool hasFirstLaunch;
final bool hasAgreementAccepted;
final bool hasAppVersion;
final List<String> allKeys;
GuideCheckResult({
required this.needGuide,
required this.reason,
required this.firstLaunch,
required this.agreementAccepted,
required this.savedVersion,
required this.hasFirstLaunch,
required this.hasAgreementAccepted,
required this.hasAppVersion,
required this.allKeys,
});
}
/// 引导页异常
class GuidePageException implements Exception {
final String message;
GuidePageException(this.message);
@override
String toString() => 'GuidePageException: $message';
}