215 lines
6.6 KiB
Dart
215 lines
6.6 KiB
Dart
// Author: fruit.com.cn
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import '../../core/data/services/auth_controller.dart';
|
|
import '../../core/theme/app_colors.dart';
|
|
import '../../core/theme/app_dimens.dart';
|
|
import '../../core/theme/app_theme.dart';
|
|
import '../../core/widgets/app_glow_panel.dart';
|
|
import '../../core/widgets/plain_page_scaffold.dart';
|
|
import '../../l10n/app_localizations.dart';
|
|
import '../account/account_entry_card.dart';
|
|
import '../mine/about_page.dart';
|
|
import 'legal_links_card.dart';
|
|
|
|
/// 设置页:账号入口按列表展示,不提供通知和手动语言切换。
|
|
class SettingsPage extends StatelessWidget {
|
|
const SettingsPage({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l10n = AppLocalizations.of(context)!;
|
|
final auth = context.watch<AuthController>();
|
|
return Theme(
|
|
data: AppTheme.dark(),
|
|
child: PlainPageScaffold(
|
|
pageKey: const Key('settings-page'),
|
|
backKey: const Key('settings-back'),
|
|
title: l10n.settings,
|
|
child: ListView(
|
|
padding: const EdgeInsets.fromLTRB(14, 8, 14, 28),
|
|
children: [
|
|
Container(
|
|
key: const Key('settings-group'),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.contentSurface,
|
|
borderRadius: BorderRadius.circular(AppDimens.cardRadius),
|
|
),
|
|
clipBehavior: Clip.antiAlias,
|
|
child: Column(
|
|
children: [
|
|
if (auth.isSignedIn) ...[
|
|
const AccountEntryCard(),
|
|
const Divider(
|
|
height: AppDimens.mineGridDividerWidth,
|
|
thickness: AppDimens.mineGridDividerWidth,
|
|
color: AppColors.contentBorder,
|
|
),
|
|
],
|
|
const LegalLinksCard(),
|
|
const Divider(
|
|
height: AppDimens.mineGridDividerWidth,
|
|
thickness: AppDimens.mineGridDividerWidth,
|
|
color: AppColors.contentBorder,
|
|
),
|
|
_supportSection(context, l10n),
|
|
],
|
|
),
|
|
),
|
|
if (auth.isSignedIn) ...[
|
|
const SizedBox(height: 12),
|
|
_signOutButton(context, l10n),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 退出登录:透明背景独立按钮,确认后清除本地会话并吊销刷新令牌。
|
|
Widget _signOutButton(BuildContext context, AppLocalizations l10n) {
|
|
return SizedBox(
|
|
width: double.infinity,
|
|
height: 48,
|
|
child: TextButton(
|
|
key: const Key('settings-sign-out'),
|
|
style: TextButton.styleFrom(
|
|
backgroundColor: AppColors.transparent,
|
|
foregroundColor: AppColors.error,
|
|
),
|
|
onPressed: () => _confirmSignOut(context, l10n),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Icon(Icons.logout_rounded, size: 18),
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
l10n.signOut,
|
|
style: const TextStyle(
|
|
fontSize: AppDimens.body,
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _confirmSignOut(BuildContext context, AppLocalizations l10n) async {
|
|
final confirmed = await showDialog<bool>(
|
|
context: context,
|
|
builder: (dialogContext) => AppGlowDialog(
|
|
title: l10n.signOut,
|
|
content: l10n.signOutConfirm,
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(dialogContext).pop(false),
|
|
child: Text(l10n.cancel),
|
|
),
|
|
TextButton(
|
|
style: TextButton.styleFrom(foregroundColor: AppColors.error),
|
|
onPressed: () => Navigator.of(dialogContext).pop(true),
|
|
child: Text(l10n.signOut),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
if (confirmed != true || !context.mounted) return;
|
|
await context.read<AuthController>().signOut();
|
|
}
|
|
|
|
/// 常见问题 / 关于我们。
|
|
Widget _supportSection(BuildContext context, AppLocalizations l10n) {
|
|
return Container(
|
|
key: const Key('settings-support'),
|
|
decoration: const BoxDecoration(color: AppColors.contentSurface),
|
|
clipBehavior: Clip.antiAlias,
|
|
child: Column(
|
|
children: [
|
|
_row(
|
|
key: const Key('settings-common-questions'),
|
|
label: l10n.helpFeedback,
|
|
icon: Icons.help_outline,
|
|
onTap: () => _pushPlaceholder(context, l10n),
|
|
),
|
|
const Divider(
|
|
height: 1,
|
|
thickness: 1,
|
|
color: AppColors.contentBorder,
|
|
),
|
|
_row(
|
|
key: const Key('settings-about'),
|
|
label: l10n.aboutUs,
|
|
icon: Icons.info_outline,
|
|
onTap: () => Navigator.of(context).push(
|
|
MaterialPageRoute<void>(builder: (_) => const MineAboutPage()),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _row({
|
|
required Key key,
|
|
required String label,
|
|
required IconData icon,
|
|
required VoidCallback onTap,
|
|
}) {
|
|
return SizedBox(
|
|
height: 56,
|
|
child: InkWell(
|
|
key: key,
|
|
onTap: onTap,
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Row(
|
|
children: [
|
|
Icon(icon, color: AppColors.textSecondary, size: 20),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: Text(
|
|
label,
|
|
style: const TextStyle(
|
|
color: AppColors.textPrimary,
|
|
fontSize: AppDimens.body,
|
|
),
|
|
),
|
|
),
|
|
const Icon(
|
|
Icons.chevron_right_rounded,
|
|
color: AppColors.textSecondary,
|
|
size: 20,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _pushPlaceholder(BuildContext context, AppLocalizations l10n) {
|
|
Navigator.of(context).push(
|
|
MaterialPageRoute<void>(
|
|
builder: (_) => PlainPageScaffold(
|
|
pageKey: const Key('settings-placeholder-page'),
|
|
backKey: const Key('settings-placeholder-back'),
|
|
title: l10n.helpFeedback,
|
|
child: Center(
|
|
child: Text(
|
|
l10n.comingSoon,
|
|
style: const TextStyle(
|
|
color: AppColors.textSecondary,
|
|
fontSize: AppDimens.body,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|