feat: 实现起卦、设置与积分系统
This commit is contained in:
@@ -28,8 +28,8 @@ class AuthBloc extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
} catch (error, stackTrace) {
|
||||
_logger.error(
|
||||
message: 'Session recovery failed',
|
||||
error: error,
|
||||
message: 'Session recovery failed: ${error.runtimeType}',
|
||||
error: error.runtimeType.toString(),
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
await _repository.clearLocalSession();
|
||||
@@ -64,8 +64,8 @@ class AuthBloc extends ChangeNotifier {
|
||||
caughtError = error;
|
||||
caughtStackTrace = stackTrace;
|
||||
_logger.error(
|
||||
message: 'User logout failed',
|
||||
error: error,
|
||||
message: 'User logout failed: ${error.runtimeType}',
|
||||
error: error.runtimeType.toString(),
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import 'package:flutter/material.dart';
|
||||
import '../../../../core/logging/logger.dart';
|
||||
import '../../../../core/network/api_problem.dart';
|
||||
import '../../../../core/network/api_problem_mapper.dart';
|
||||
import '../../../settings/presentation/models/legal_document_type.dart';
|
||||
import '../../../settings/presentation/screens/legal_document_screen.dart';
|
||||
import '../../../settings/presentation/utils/legal_document_assets.dart';
|
||||
import '../../../../l10n/app_localizations.dart';
|
||||
import '../../../../shared/theme/design_tokens.dart';
|
||||
import '../../../../shared/widgets/toast/toast.dart';
|
||||
@@ -171,6 +174,21 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _openLegalDocument(LegalDocumentType type) async {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
await Navigator.of(context).push<void>(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => LegalDocumentScreen(
|
||||
title: legalDocumentTitle(l10n, type),
|
||||
assetPath: legalDocumentAssetPath(
|
||||
Localizations.localeOf(context),
|
||||
type,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
@@ -190,51 +208,49 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: AppSpacing.xxxl),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
l10n.welcomeLogin,
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
const SizedBox(height: AppSpacing.sm),
|
||||
Text(
|
||||
l10n.loginSubtitleEmail,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
],
|
||||
const SizedBox(height: AppSpacing.xxl),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(AppSpacing.xl),
|
||||
decoration: BoxDecoration(
|
||||
color: colors.surface,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
l10n.welcomeLogin,
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
),
|
||||
PopupMenuButton<Locale>(
|
||||
icon: Icon(Icons.language, color: colors.primary),
|
||||
onSelected: widget.onLocaleChanged,
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem<Locale>(
|
||||
value: const Locale('zh'),
|
||||
child: Text(l10n.chinese),
|
||||
),
|
||||
PopupMenuItem<Locale>(
|
||||
value: const Locale('en'),
|
||||
child: Text(l10n.english),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
const SizedBox(height: AppSpacing.sm),
|
||||
Text(
|
||||
l10n.loginSubtitleEmail,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: AppSpacing.xxl),
|
||||
TextField(
|
||||
controller: _emailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
onChanged: (_) => setState(() {}),
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.emailHint,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: colors.surface,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
child: TextField(
|
||||
controller: _emailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
onChanged: (_) => setState(() {}),
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.emailHint,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.lg,
|
||||
vertical: AppSpacing.lg,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -242,16 +258,27 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _codeController,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 6,
|
||||
onChanged: (_) => setState(() {}),
|
||||
decoration: InputDecoration(
|
||||
counterText: '',
|
||||
hintText: l10n.codeHint,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: colors.surface,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
child: TextField(
|
||||
controller: _codeController,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 6,
|
||||
onChanged: (_) => setState(() {}),
|
||||
decoration: InputDecoration(
|
||||
counterText: '',
|
||||
hintText: l10n.codeHint,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.lg,
|
||||
vertical: AppSpacing.lg,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -265,7 +292,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
backgroundColor: colors.surfaceContainerHighest,
|
||||
foregroundColor: colors.primary,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
borderRadius: BorderRadius.circular(AppRadius.full),
|
||||
),
|
||||
),
|
||||
onPressed: _sendCode,
|
||||
@@ -288,18 +315,16 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
backgroundColor: colors.primary,
|
||||
foregroundColor: colors.onPrimary,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
borderRadius: BorderRadius.circular(AppRadius.full),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: AppSpacing.md,
|
||||
),
|
||||
),
|
||||
onPressed: canLogin ? _login : null,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: AppSpacing.sm,
|
||||
),
|
||||
child: Text(
|
||||
l10n.login,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
child: Text(
|
||||
l10n.login,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -329,9 +354,8 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => _showPolicyDialog(
|
||||
l10n.privacyPolicy,
|
||||
l10n.privacyContent,
|
||||
..onTap = () => _openLegalDocument(
|
||||
LegalDocumentType.privacyPolicy,
|
||||
),
|
||||
),
|
||||
TextSpan(text: l10n.agreementSeparator),
|
||||
@@ -342,9 +366,8 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => _showPolicyDialog(
|
||||
l10n.termsOfService,
|
||||
l10n.termsContent,
|
||||
..onTap = () => _openLegalDocument(
|
||||
LegalDocumentType.termsOfService,
|
||||
),
|
||||
),
|
||||
TextSpan(text: l10n.agreementAnd),
|
||||
|
||||
Reference in New Issue
Block a user