// Author: fruit.com.cn import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.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/widgets/centered_toast.dart'; import '../../../core/widgets/remote_image.dart'; import '../../../l10n/app_localizations.dart'; const double _buttonHeight = 34; const double _buttonRadius = 20; const double _copyIconSize = 15; /// 「我的」页用户区。 class MineHeader extends StatelessWidget { const MineHeader({super.key, required this.onLogin, required this.onEdit}); final VoidCallback onLogin; final VoidCallback onEdit; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final auth = context.watch(); final user = auth.user; final signedIn = auth.isSignedIn; final nickname = signedIn && (user?.nickname.trim().isNotEmpty ?? false) ? user!.nickname.trim() : l10n.visitor; final uid = signedIn ? user?.uid.trim() ?? '' : ''; return Padding( key: const Key('mine-user-row'), padding: const EdgeInsets.symmetric(vertical: AppDimens.spaceMd), child: Row( children: [ _avatar(user?.avatarUrl ?? ''), const SizedBox(width: AppDimens.spaceMd), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( nickname, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontFamily: 'Outfit', color: AppColors.textPrimary, fontSize: AppDimens.mineUserName, fontWeight: FontWeight.w700, ), ), const SizedBox(height: AppDimens.spaceXs), Row( children: [ Flexible( child: Text( '${l10n.accountUid}: ${uid.isEmpty ? '--' : uid}', key: const Key('mine-uid'), maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.textSecondary, fontSize: AppDimens.mineUid, ), ), ), const SizedBox(width: AppDimens.spaceXs), IconButton( key: const Key('mine-uid-copy'), tooltip: l10n.copyUid, onPressed: uid.isEmpty ? null : () => unawaited( _copyUid(context, uid, l10n.uidCopied), ), visualDensity: VisualDensity.compact, constraints: const BoxConstraints.tightFor( width: AppDimens.tapTarget, height: AppDimens.tapTarget, ), padding: EdgeInsets.zero, icon: const Icon( Icons.copy_rounded, color: AppColors.textSecondary, size: _copyIconSize, ), ), ], ), ], ), ), const SizedBox(width: AppDimens.spaceSm), _accountButton( key: signedIn ? const Key('mine-edit') : const Key('mine-login'), label: signedIn ? l10n.edit : l10n.logIn, onTap: signedIn ? onEdit : onLogin, ), ], ), ); } Widget _avatar(String path) { return Container( key: const Key('mine-avatar'), width: AppDimens.mineAvatar, height: AppDimens.mineAvatar, decoration: const BoxDecoration( color: AppColors.contentSurface, shape: BoxShape.circle, ), clipBehavior: Clip.antiAlias, child: path.isEmpty ? const Icon( Icons.person_rounded, color: AppColors.textPrimary, size: 28, ) : RemoteImage(path, fit: BoxFit.cover), ); } Widget _accountButton({ required Key key, required String label, required VoidCallback onTap, }) { return OutlinedButton( key: key, onPressed: onTap, style: OutlinedButton.styleFrom( minimumSize: const Size(0, _buttonHeight), padding: const EdgeInsets.symmetric(horizontal: AppDimens.spaceMd), foregroundColor: AppColors.textPrimary, side: const BorderSide(color: AppColors.mineOutline), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(_buttonRadius), ), textStyle: const TextStyle( fontSize: AppDimens.body, fontWeight: FontWeight.w500, ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text(label), const SizedBox(width: 2), const Icon(Icons.chevron_right_rounded, size: 17), ], ), ); } Future _copyUid( BuildContext context, String uid, String message, ) async { await Clipboard.setData(ClipboardData(text: uid)); if (context.mounted) showCenteredToast(context, message); } }