import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:formz/formz.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/theme/design_tokens.dart'; import '../../../../core/di/injection.dart'; import '../../../../shared/widgets/app_button.dart'; import '../../../../shared/widgets/banner/app_banner.dart'; import '../../../../shared/widgets/toast/toast.dart'; import '../../../../shared/widgets/toast/toast_type.dart'; import '../../presentation/cubits/register_cubit.dart'; import '../../data/auth_repository.dart'; class RegisterScreen extends StatelessWidget { const RegisterScreen({super.key}); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => RegisterCubit(sl()), child: const RegisterView(), ); } } class RegisterView extends StatefulWidget { const RegisterView({super.key}); @override State createState() => _RegisterViewState(); } class _RegisterViewState extends State { final _nicknameController = TextEditingController(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); bool _obscureText = true; @override void dispose() { _nicknameController.dispose(); _emailController.dispose(); _passwordController.dispose(); super.dispose(); } Future _handleNext() async { final cubit = context.read(); cubit.usernameChanged(_nicknameController.text); cubit.emailChanged(_emailController.text); cubit.passwordChanged(_passwordController.text); if (!cubit.state.isStep1Valid || cubit.state.isSending) { String? errorMsg; if (!cubit.state.username.isValid) { errorMsg = '请输入有效的昵称(3-30个字符)'; } else if (!cubit.state.email.isValid) { errorMsg = '请输入有效的邮箱地址'; } else if (!cubit.state.password.isValid) { errorMsg = '密码至少需要6个字符'; } if (errorMsg != null && mounted) { Toast.show(context, errorMsg, type: ToastType.warning); } return; } if (mounted) { context.push('/register/verification', extra: cubit); } unawaited(cubit.sendCodeSilently()); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.background, body: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Center( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildAppIcon(), const SizedBox(height: 24), _buildAppTitle(), const SizedBox(height: 24), _buildFormContainer(), ], ), ), ), _buildFooter(), const SizedBox(height: 24), ], ), ), ), ); } Widget _buildAppIcon() { return Container( width: 104, height: 104, decoration: BoxDecoration( color: AppColors.appIconRing, borderRadius: BorderRadius.circular(52), border: Border.all(color: AppColors.appIconBorder, width: 1), ), child: Center( child: ClipRRect( borderRadius: BorderRadius.circular(38), child: Image.asset( 'assets/images/logo.png', width: 76, height: 76, fit: BoxFit.cover, ), ), ), ); } Widget _buildAppTitle() { return const Text( 'linksy', style: TextStyle( fontFamily: 'Playfair Display', fontSize: 34, fontWeight: FontWeight.w700, fontStyle: FontStyle.italic, color: AppColors.appTitle, letterSpacing: 0.5, ), ); } Widget _buildFormContainer() { return BlocBuilder( builder: (context, state) { return SizedBox( width: 327, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _buildInput('昵称', '请输入昵称', _nicknameController), const SizedBox(height: 12), _buildInput('邮箱', '请输入邮箱', _emailController), const SizedBox(height: 12), _buildPasswordInput(), const SizedBox(height: 12), _buildStepIndicator(), if (state.errorMessage != null) Padding( padding: const EdgeInsets.only(top: 8), child: AppBanner( message: state.errorMessage!, type: ToastType.error, ), ), const SizedBox(height: 12), AppButton( text: '下一步', onPressed: state.status == FormzSubmissionStatus.inProgress || state.isSending ? null : _handleNext, ), ], ), ); }, ); } Widget _buildInput( String label, String hint, TextEditingController controller, ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: Color(0xFF475569), ), ), const SizedBox(height: 6), TextField( controller: controller, decoration: InputDecoration(hintText: hint), ), ], ); } Widget _buildPasswordInput() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '密码', style: TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: Color(0xFF475569), ), ), const SizedBox(height: 6), TextField( controller: _passwordController, obscureText: _obscureText, decoration: InputDecoration( hintText: '请输入至少 6 位密码', suffixIcon: IconButton( icon: Icon( _obscureText ? Icons.visibility_off : Icons.visibility, size: 20, color: AppColors.slate400, ), onPressed: () { setState(() { _obscureText = !_obscureText; }); }, ), ), ), ], ); } Widget _buildStepIndicator() { return Row( children: [ Expanded( child: Container( height: 4, decoration: BoxDecoration( color: AppColors.primary, borderRadius: BorderRadius.circular(99), ), ), ), const SizedBox(width: 6), Expanded( child: Container( height: 4, decoration: BoxDecoration( color: const Color(0xFFDCE3EC), borderRadius: BorderRadius.circular(99), ), ), ), ], ); } Widget _buildFooter() { return GestureDetector( onTap: () => context.pop(), child: const Text( '已有账号?去登录', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.slate500, ), ), ); } }