rwadurian/frontend/mobile-app/lib/features/auth/presentation/pages/splash_page.dart

269 lines
8.1 KiB
Dart
Raw 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:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:video_player/video_player.dart';
import '../../../../routes/route_paths.dart';
import '../../../../routes/app_router.dart';
import '../../../../bootstrap.dart';
import '../providers/auth_provider.dart';
/// 开屏页面 - 应用启动时显示的第一个页面
/// 播放开屏视频,视频结束后检查用户认证状态并跳转
class SplashPage extends ConsumerStatefulWidget {
const SplashPage({super.key});
@override
ConsumerState<SplashPage> createState() => _SplashPageState();
}
class _SplashPageState extends ConsumerState<SplashPage> {
/// 视频播放控制器
VideoPlayerController? _videoController;
/// 视频是否已初始化
bool _isVideoInitialized = false;
/// 是否显示跳过按钮
bool _showSkipButton = false;
/// 是否已经开始跳转(防止重复跳转)
bool _isNavigating = false;
@override
void initState() {
super.initState();
_initializeVideo();
}
@override
void dispose() {
_videoController?.removeListener(_onVideoStateChanged);
_videoController?.dispose();
super.dispose();
}
/// 初始化视频播放器
Future<void> _initializeVideo() async {
try {
// 从 assets 加载视频
_videoController = VideoPlayerController.asset('assets/videos/splash.mp4');
await _videoController!.initialize();
if (mounted) {
setState(() {
_isVideoInitialized = true;
});
// 设置视频播放完成监听
_videoController!.addListener(_onVideoStateChanged);
// 开始播放视频
await _videoController!.play();
// 1秒后显示跳过按钮
Future.delayed(const Duration(seconds: 1), () {
if (mounted) {
setState(() {
_showSkipButton = true;
});
}
});
}
} catch (e) {
debugPrint('[SplashPage] 视频初始化失败: $e');
// 如果视频加载失败,直接进行跳转
_navigateToNextPage();
}
}
/// 视频状态变化监听
void _onVideoStateChanged() {
if (_videoController == null) return;
// 视频播放完成
if (_videoController!.value.position >= _videoController!.value.duration &&
_videoController!.value.duration > Duration.zero) {
_navigateToNextPage();
}
}
/// 跳过视频
void _skipVideo() {
_videoController?.pause();
_navigateToNextPage();
}
/// 导航到下一个页面
Future<void> _navigateToNextPage() async {
// 防止重复跳转
if (_isNavigating) return;
_isNavigating = true;
// 初始化遥测服务(需要 BuildContext
await initializeTelemetry(context);
// 检查认证状态
await ref.read(authProvider.notifier).checkAuthStatus();
if (!mounted) return;
final authState = ref.read(authProvider);
// 根据认证状态决定跳转目标
// 优先级:
// 1. 钱包已创建且已备份 → 主页面
// 2. 账号已创建但钱包未完成 → 备份助记词页面
// 3. 首次打开或未看过向导 → 向导页
// 4. 其他情况 → 创建账户页面
if (authState.isWalletCreated) {
// 已创建钱包且已备份,进入主页面(龙虎榜)
debugPrint('[SplashPage] 钱包已创建且已备份 → 跳转到龙虎榜');
context.go(RoutePaths.ranking);
} else if (authState.isAccountCreated && authState.userSerialNum != null) {
// 账号已创建但钱包未完成(可能正在生成或未备份),直接进入备份助记词页面
debugPrint('[SplashPage] 账号已创建但钱包未完成 → 跳转到备份助记词页面');
debugPrint('[SplashPage] userSerialNum: ${authState.userSerialNum}, isWalletReady: ${authState.isWalletReady}');
context.go(
RoutePaths.backupMnemonic,
extra: BackupMnemonicParams(
userSerialNum: authState.userSerialNum!,
referralCode: authState.referralCode,
),
);
} else if (authState.isFirstLaunch || !authState.hasSeenGuide) {
// 首次打开或未看过向导,进入向导页
debugPrint('[SplashPage] 首次打开或未看过向导 → 跳转到向导页');
context.go(RoutePaths.guide);
} else {
// 已看过向导但未创建钱包,直接进入创建账户页面
debugPrint('[SplashPage] 已看过向导但未创建钱包 → 跳转到创建账户页面');
context.go(RoutePaths.onboarding);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Stack(
fit: StackFit.expand,
children: [
// 视频播放器(全屏覆盖)
if (_isVideoInitialized && _videoController != null)
SizedBox.expand(
child: FittedBox(
fit: BoxFit.cover,
child: SizedBox(
width: _videoController!.value.size.width,
height: _videoController!.value.size.height,
child: VideoPlayer(_videoController!),
),
),
)
else
// 视频加载中显示 Logo
_buildLoadingView(),
// 跳过按钮
if (_showSkipButton)
Positioned(
top: MediaQuery.of(context).padding.top + 16,
right: 16,
child: _buildSkipButton(),
),
],
),
);
}
/// 构建加载中视图(视频未加载完成时显示)
Widget _buildLoadingView() {
return Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFFFF5E6),
Color(0xFFFFE4B5),
],
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Logo
Image.asset(
'assets/images/logo/app_icon.png',
width: 128,
height: 128,
),
const SizedBox(height: 24),
const Text(
'榴莲皇后',
style: TextStyle(
fontSize: 32,
fontFamily: 'Noto Sans SC',
fontWeight: FontWeight.w700,
height: 1.25,
letterSpacing: 1.6,
color: Color(0xFF4A3F35),
),
),
const SizedBox(height: 24),
// 加载指示器
const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Color(0xFFD4AF37)),
),
),
],
),
);
}
/// 构建跳过按钮
Widget _buildSkipButton() {
return GestureDetector(
onTap: _skipVideo,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.black.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: Colors.white.withValues(alpha: 0.3),
width: 1,
),
),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'跳过',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
SizedBox(width: 4),
Icon(
Icons.skip_next,
size: 18,
color: Colors.white,
),
],
),
),
);
}
}