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

374 lines
11 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/gestures.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../../routes/route_paths.dart';
import '../../../../routes/app_router.dart';
import '../../../../core/di/injection_container.dart';
import '../../../../core/services/account_service.dart';
/// 创建账号页面 - 用户首次进入应用时的引导页面
/// 提供创建钱包和导入助记词两种选项
class OnboardingPage extends ConsumerStatefulWidget {
const OnboardingPage({super.key});
@override
ConsumerState<OnboardingPage> createState() => _OnboardingPageState();
}
class _OnboardingPageState extends ConsumerState<OnboardingPage> {
// 用户协议勾选状态
bool _isAgreed = false;
// 创建钱包加载状态
bool _isCreating = false;
// 错误信息
String? _errorMessage;
/// 创建钱包并跳转到备份页面
///
/// 调用后端 API 使用 MPC 2-of-3 协议生成钱包地址
Future<void> _createWallet() async {
if (!_isAgreed) {
_showAgreementTip();
return;
}
setState(() {
_isCreating = true;
_errorMessage = null;
});
try {
// 获取 AccountService
final accountService = ref.read(accountServiceProvider);
// 调用后端 API 创建账号
debugPrint('开始创建账号...');
final response = await accountService.createAccount();
debugPrint('账号创建成功: 序列号=${response.accountSequence}');
if (!mounted) return;
// MPC 模式下,检查是否有客户端分片数据
// 如果有分片数据,需要提示用户妥善保管
final hasMpcData = response.clientShareData != null &&
response.clientShareData!.isNotEmpty;
// 跳转到钱包创建成功页面
context.push(
RoutePaths.backupMnemonic,
extra: BackupMnemonicParams(
// MPC 模式下助记词为空,显示账号信息即可
mnemonicWords: response.mnemonic?.isNotEmpty == true
? response.mnemonic!.split(' ')
: [], // MPC 模式下为空
kavaAddress: response.walletAddresses.kava,
dstAddress: response.walletAddresses.dst,
bscAddress: response.walletAddresses.bsc,
serialNumber: response.accountSequence.toString(),
referralCode: response.referralCode,
publicKey: response.publicKey,
isMpcMode: hasMpcData, // 标记是否为 MPC 模式
),
);
} catch (e) {
debugPrint('创建账号失败: $e');
if (!mounted) return;
setState(() {
_errorMessage = e.toString();
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('创建账号失败: ${e.toString().replaceAll('Exception: ', '')}'),
backgroundColor: Colors.red,
duration: const Duration(seconds: 5),
),
);
} finally {
if (mounted) {
setState(() => _isCreating = false);
}
}
}
/// 显示需要同意协议的提示
void _showAgreementTip() {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('请先阅读并同意用户协议和隐私政策'),
backgroundColor: Color(0xFFD4AF37),
),
);
}
/// 显示用户协议
void _showUserAgreement() {
// TODO: 跳转到用户协议页面
debugPrint('显示用户协议');
}
/// 显示隐私政策
void _showPrivacyPolicy() {
// TODO: 跳转到隐私政策页面
debugPrint('显示隐私政策');
}
/// 导入助记词
void _importMnemonic() {
// TODO: 跳转到导入助记词页面
debugPrint('导入助记词');
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
height: double.infinity,
// 渐变背景 - 从浅米色到金黄色
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFFFF5E6), // 浅米色
Color(0xFFFFE4B5), // 金黄色
],
),
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15),
child: Column(
children: [
// 顶部 Logo 和标题区域
_buildHeader(),
const SizedBox(height: 48),
// 创建账户说明区域
_buildDescription(),
const Spacer(),
// 底部操作区域
_buildActionSection(),
const SizedBox(height: 9),
],
),
),
),
),
);
}
/// 构建顶部 Logo 和标题
Widget _buildHeader() {
return Column(
children: [
const SizedBox(height: 32),
// Logo 容器
Container(
width: 100,
height: 80,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: const Center(
child: Text(
'ap',
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w600,
color: Color(0xFF2E7D32), // 绿色
),
),
),
),
const SizedBox(height: 24),
// 应用标题
const Text(
'榴莲女皇',
style: TextStyle(
fontSize: 32,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037), // 深棕色
),
),
],
);
}
/// 构建创建账户说明区域
Widget _buildDescription() {
return Column(
children: [
// 标题
const Text(
'创建账户',
style: TextStyle(
fontSize: 22,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
letterSpacing: -0.33,
color: Color(0xFF5D4037),
),
),
const SizedBox(height: 16),
// 说明文字
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Text(
'我们将为你创建三个链的钱包地址KAVA / DST / BSC同时生成唯一序列号用于推荐与权益。',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xFF5D4037),
),
textAlign: TextAlign.center,
),
),
],
);
}
/// 构建底部操作区域
Widget _buildActionSection() {
return Column(
children: [
// 生成钱包按钮
_buildCreateButton(),
const SizedBox(height: 20),
// 用户协议勾选
_buildAgreementCheckbox(),
const SizedBox(height: 24),
// 导入助记词链接
_buildImportLink(),
],
);
}
/// 构建创建钱包按钮
Widget _buildCreateButton() {
return GestureDetector(
onTap: _isCreating ? null : _createWallet,
child: Opacity(
opacity: _isAgreed ? 1.0 : 0.5,
child: Container(
width: double.infinity,
height: 48,
decoration: BoxDecoration(
color: const Color(0xFFD4AF37), // 金色
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: _isCreating
? const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: const Text(
'生成钱包(创建账户)',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
letterSpacing: 0.24,
color: Colors.white,
),
),
),
),
),
);
}
/// 构建用户协议勾选框
Widget _buildAgreementCheckbox() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 勾选框
SizedBox(
width: 20,
height: 20,
child: Checkbox(
value: _isAgreed,
onChanged: (value) {
setState(() {
_isAgreed = value ?? false;
});
},
activeColor: const Color(0xFFD4AF37),
side: const BorderSide(color: Color(0xFF5D4037)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
),
),
const SizedBox(width: 8),
// 协议文字
Flexible(
child: RichText(
text: TextSpan(
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.43,
color: Color(0xFF5D4037),
),
children: [
const TextSpan(text: '我已阅读并同意 '),
TextSpan(
text: '《用户协议》',
style: const TextStyle(color: Color(0xFFD4AF37)),
recognizer: TapGestureRecognizer()..onTap = _showUserAgreement,
),
TextSpan(
text: '《隐私政策》',
style: const TextStyle(color: Color(0xFFD4AF37)),
recognizer: TapGestureRecognizer()..onTap = _showPrivacyPolicy,
),
],
),
),
),
],
);
}
/// 构建导入助记词链接
Widget _buildImportLink() {
return GestureDetector(
onTap: _importMnemonic,
child: const Text(
'已有账号? 导入助记词',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.43,
color: Color(0xFFD4AF37),
),
),
);
}
}