import 'dart:async'; import 'dart:io'; import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import '../../../data/models/appconfig.dart'; import '../../../data/models/appconfig_model.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import '../../../data/models/user_Info.dart'; import '../../../routes/app_routes.dart'; import '../../../core/themes/theme_service.dart'; import '../../../data/services/network/api.dart'; import '../../../data/services/version_update_service.dart'; import '../../../modules/common/widgets/version_update_dialog.dart'; import '../../../modules/common/widgets/privacy_policy_dialog.dart'; import '../../../core/utils/logger.dart'; class SplashController extends GetxController { final GetStorage _storage = GetStorage(); static const String _tag = 'SplashCtrl'; // 进度条动画控制 final _loadingProgress = 0.0.obs; double get loadingProgress => _loadingProgress.value; // 各项任务完成状态 final _isTrackingPermissionRequested = false.obs; // 追踪权限请求完成 final _isVersionCheckCompleted = false.obs; // 版本检查完成 final _isTokenValidated = false.obs; // Token验证完成 final _isAppConfigLoaded = false.obs; // 应用配置加载完成 final _isAnimationCompleted = false.obs; // 动画完成 // 登录状态 final _isLoggedIn = false.obs; bool get isLoggedIn => _isLoggedIn.value; final _hasAcceptedPrivacy = false.obs; //是否同意隐私政策 // 版本号 //final String version = 'V1.0.0'; // 主题服务 final ThemeService _themeService = ThemeService(); // 会话级别的版本检查标记(静态变量,整个应用会话期间保持) static bool _hasCheckedVersionInSession = false; // 版本检查相关常量 static const String _lastVersionCheckKey = 'last_version_check_timestamp'; static const int _versionCheckIntervalHours = 24; // 24小时间隔 @override void onInit() { super.onInit(); // 首先检查隐私政策状态 final hasAcceptedPrivacy = _storage.read('hasAcceptedPrivacy') ?? false; WidgetsBinding.instance.addPostFrameCallback((_) { if (!hasAcceptedPrivacy) { // 优先显示隐私政策弹窗,暂停其他初始化 _showPrivacyDialog(); } else { // 已同意隐私政策,正常启动流程 _startNormalFlow(); } }); // 注意:追踪权限请求将在用户同意隐私政策后执行 } /// 异步请求追踪权限 Future _requestTrackingPermissionAsync() async { try { await AppTrackingTransparency.requestTrackingAuthorization(); Logger.d(_tag, '用户追踪权限请求完成'); } catch (e) { Logger.e(_tag, '用户追踪权限请求失败: $e'); } finally { _isTrackingPermissionRequested.value = true; } } void _startNormalFlow() { _startLoadingAnimation(); _startParallelTasks(); } /// 启动并行任务:在1.5秒动画期间同时执行多个任务 void _startParallelTasks() { // 并行执行所有任务 _requestTrackingPermissionAsync(); _performVersionCheckAsync(); _validateTokenAsync(); } /// 异步执行版本检查 Future _performVersionCheckAsync() async { try { Logger.d(_tag, '开始执行版本检查'); await _checkVersionUpdateIfNeeded(); } catch (e) { Logger.e(_tag, '版本检查失败: $e'); } //finally { // _isVersionCheckCompleted.value = true; // } } void _onPrivacyAccepted() { _storage.write('hasAcceptedPrivacy', true); Get.back(); // 关闭弹窗 _startNormalFlow(); // 开始正常流程(已包含版本检查) } void _onPrivacyRejected() { exit(0); // 退出应用 } // 显示隐私政策弹窗 void _showPrivacyDialog() { PrivacyPolicyDialog.show( onAccept: () { _onPrivacyAccepted(); _hasAcceptedPrivacy.value = true; }, onReject: _onPrivacyRejected, canDismiss: false, // 禁止通过返回键关闭弹窗 ); } // 进度条动画(持续1.5秒) void _startLoadingAnimation() { const totalDuration = 1500; // 动画总时长1.5秒 const steps = totalDuration ~/ 30; // 30ms间隔,更平滑的动画 const stepValue = 1.0 / steps; Timer.periodic(const Duration(milliseconds: 30), (timer) { if (_loadingProgress.value < 1.0) { _loadingProgress.value += stepValue; } else { timer.cancel(); _isAnimationCompleted.value = true; _checkNavigateCondition(); } }); } /// 异步验证Token和加载应用配置 Future _validateTokenAsync() async { try { bool isLoggedIn = false; final token = _storage.read('logintoken'); Logger.d(_tag, 'Token验证开始: $token'); if (token != null && token.isNotEmpty) { isLoggedIn = await getLoginToken(); if (isLoggedIn) { await getAppConfig(); _isAppConfigLoaded.value = true; } } _isLoggedIn.value = isLoggedIn; Logger.d(_tag, 'Token验证完成,登录状态: $isLoggedIn'); } catch (e) { Logger.e(_tag, 'Token验证失败: $e'); _isLoggedIn.value = false; } finally { _isTokenValidated.value = true; } } // 检查跳转条件:所有任务都完成后才跳转 void _checkNavigateCondition() { if (_isAnimationCompleted.value && _isTrackingPermissionRequested.value && _isVersionCheckCompleted.value && _isTokenValidated.value) { _navigateToTargetPage(); } } // 根据登录状态跳转到目标页面 void _navigateToTargetPage() { if (_isLoggedIn.value && _isAppConfigLoaded.value) { Get.offAllNamed(Routes.pairing); } else { Get.offAllNamed(Routes.login); } } Future getLoginToken() async { try { Logger.d(_tag, 'getLoginToken:进来了'); //if (User.getname() != "") { final response = await Api.tokenlogin(); Logger.d(_tag, 'getLoginToken: $response'); if (response == null) return false; if (response['user'] != '') { Logger.d(_tag, 'getLoginToken:进来了'); // 根据API设计调整 final user = User.fromJson(response); // 存储用户信息(示例) await _storage.write('user_info', user.toJson()); return true; } //return true; //} return false; } catch (e) { Logger.e(_tag, 'Token获取失败: $e'); return false; } } Future getAppConfig() async { try { Logger.d(_tag, 'getAppConfig:进来了'); //if (User.getname() != "") { final response = await Api.getappconfig(); Logger.d(_tag, 'getAppConfig: $response'); if (response == null) return false; // 根据API设计调整 final resp = UserGetAppConfigResp.fromJson(response); Logger.d(_tag, 'getAppConfig:进来了'); // 存储用户信息(示例) // _storage.write('ENV', resp.env); // _storage.write('AGENTS', resp.agents); // _storage.write('MCPS', resp.mcps); AppConfig.initialize(resp); return true; } catch (e) { Logger.e(_tag, 'getAppConfig 取失败: $e'); return false; } } /// 混合检查机制:判断是否需要进行版本检查 /// 检查条件:1. 会话内未检查过 OR 2. 距离上次检查超过24小时 Future _checkVersionUpdateIfNeeded() async { try { final now = DateTime.now(); final lastCheckTimestamp = _storage.read(_lastVersionCheckKey); bool shouldCheck = false; String reason = ''; // 条件1:会话内未检查过 if (!_hasCheckedVersionInSession) { shouldCheck = true; reason = '会话内首次检查'; } // 条件2:距离上次检查超过24小时 else if (lastCheckTimestamp != null) { final lastCheckTime = DateTime.fromMillisecondsSinceEpoch(lastCheckTimestamp); final timeDifference = now.difference(lastCheckTime); if (timeDifference.inHours >= _versionCheckIntervalHours) { shouldCheck = true; reason = '距离上次检查已超过${_versionCheckIntervalHours}小时'; } } // 条件3:从未检查过(首次使用应用) else { shouldCheck = true; reason = '首次使用应用'; } if (shouldCheck) { Logger.i(_tag, '开始版本检查 - 原因: $reason'); await _performVersionCheck(); } else { Logger.i(_tag, '跳过版本检查 - 会话内已检查且未超过时间间隔'); } } catch (e) { Logger.e(_tag, '版本检查判断失败: $e'); } } /// 执行版本检查(在后台进行,不阻塞启动流程) Future _performVersionCheck() async { try { final versionService = VersionUpdateService.to; // 异步执行,不等待结果 versionService.checkForUpdate().then((updateInfo) { if (updateInfo.hasUpdate) { Logger.i(_tag, '发现新版本: ${updateInfo.latestVersion}'); // 在主线程中显示更新对话框 WidgetsBinding.instance.addPostFrameCallback((_) { VersionUpdateDialog.show(updateInfo).then((_) { // 无论用户选择更新还是稍后提醒,都标记版本检查完成 _isVersionCheckCompleted.value = true; _checkNavigateCondition(); }); }); } else { _isVersionCheckCompleted.value = true; Logger.i(_tag, '当前已是最新版本: ${updateInfo.currentVersion}'); } // 更新检查记录 _updateVersionCheckRecord(); }).catchError((e) { Logger.e(_tag, '版本检查失败: $e'); // 即使检查失败,也标记版本检查完成,让流程继续 _isVersionCheckCompleted.value = true; // 更新检查记录,避免频繁重试 _updateVersionCheckRecord(); }); } catch (e) { Logger.e(_tag, '版本检查失败: $e'); // 即使检查失败,也标记版本检查完成,让流程继续 _isVersionCheckCompleted.value = true; // 更新检查记录,避免频繁重试 _updateVersionCheckRecord(); } } /// 更新版本检查记录 void _updateVersionCheckRecord() { try { // 更新时间戳 final now = DateTime.now(); _storage.write(_lastVersionCheckKey, now.millisecondsSinceEpoch); // 标记本次会话已检查过版本 _hasCheckedVersionInSession = true; Logger.i(_tag, '版本检查记录已更新: ${now.toIso8601String()}'); } catch (e) { Logger.e(_tag, '更新版本检查记录失败: $e'); } } /// 重置版本检查标记(可用于强制重新检查) /// 注意:这会清除会话标记,但不会清除时间戳记录 static void resetVersionCheckFlag() { _hasCheckedVersionInSession = false; Logger.i('SplashCtrl', '版本检查会话标记已重置'); } /// 完全重置版本检查状态(包括时间戳) /// 用于测试或特殊情况下强制重新检查 void forceResetVersionCheck() { try { _hasCheckedVersionInSession = false; _storage.remove(_lastVersionCheckKey); Logger.i(_tag, '版本检查状态已完全重置'); } catch (e) { Logger.e(_tag, '重置版本检查状态失败: $e'); } } }