Files
ReelShort/lib/pages/auth/auth_widgets.dart

182 lines
5.0 KiB
Dart

// Author: fruit.com.cn
part of 'auth_view.dart';
class _AuthCardState {
const _AuthCardState({
required this.l10n,
required this.status,
required this.fields,
});
final AppLocalizations l10n;
final _AuthFormStatus status;
final _AuthFieldControllers fields;
}
class _AuthFormStatus {
const _AuthFormStatus({
required this.signUpMode,
required this.busy,
required this.errorMessage,
required this.fieldError,
required this.obscurePassword,
});
final bool signUpMode;
final bool busy;
final String? errorMessage;
final AuthFieldError? fieldError;
final bool obscurePassword;
}
class _AuthFieldControllers {
const _AuthFieldControllers({
required this.email,
required this.password,
required this.emailFocus,
required this.passwordFocus,
});
final TextEditingController email;
final TextEditingController password;
final FocusNode emailFocus;
final FocusNode passwordFocus;
}
class _AuthCardCallbacks {
const _AuthCardCallbacks({
required this.onModeSelected,
required this.onEmailChanged,
required this.onPasswordChanged,
required this.onTogglePasswordVisibility,
required this.onSubmit,
});
final ValueChanged<bool> onModeSelected;
final ValueChanged<String> onEmailChanged;
final ValueChanged<String> onPasswordChanged;
final VoidCallback onTogglePasswordVisibility;
final VoidCallback onSubmit;
}
class _AuthCard extends StatelessWidget {
const _AuthCard({required this.state, required this.callbacks});
final _AuthCardState state;
final _AuthCardCallbacks callbacks;
@override
Widget build(BuildContext context) {
final l10n = state.l10n;
final status = state.status;
return Container(
key: const Key('auth-card'),
padding: const EdgeInsets.all(_cardPadding),
decoration: BoxDecoration(
color: AppColors.card,
borderRadius: BorderRadius.circular(_cardRadius),
border: Border.all(color: AppColors.border),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_AuthModeSwitch(
l10n: l10n,
signUpMode: status.signUpMode,
busy: status.busy,
onSelected: callbacks.onModeSelected,
),
const SizedBox(height: 22),
Text(
status.signUpMode ? l10n.authSignUpTitle : l10n.authSignInTitle,
style: const TextStyle(
color: AppColors.onSurface,
fontSize: 25,
fontWeight: FontWeight.w800,
height: 1.2,
),
),
const SizedBox(height: 6),
Text(
status.signUpMode ? l10n.authSignUpSubtitle : l10n.authSubtitle,
style: const TextStyle(
color: AppColors.muted,
fontSize: AppDimens.body,
height: 1.45,
),
),
const SizedBox(height: 22),
_AuthFields(state: state, callbacks: callbacks),
if (status.errorMessage != null) ...[
const SizedBox(height: 14),
_AuthError(message: status.errorMessage!),
],
const SizedBox(height: 22),
_AuthSubmitButton(state: state, onSubmit: callbacks.onSubmit),
],
),
);
}
}
class _AuthModeSwitch extends StatelessWidget {
const _AuthModeSwitch({
required this.l10n,
required this.signUpMode,
required this.busy,
required this.onSelected,
});
final AppLocalizations l10n;
final bool signUpMode;
final bool busy;
final ValueChanged<bool> onSelected;
@override
Widget build(BuildContext context) {
return TextButton(
key: const Key('auth-switch-mode'),
onPressed: busy ? null : () => onSelected(!signUpMode),
style: TextButton.styleFrom(
minimumSize: const Size(0, _minTapTarget),
padding: EdgeInsets.zero,
overlayColor: AppColors.transparent,
splashFactory: NoSplash.splashFactory,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(22)),
),
child: Container(
height: 36,
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: AppColors.raised,
borderRadius: BorderRadius.circular(18),
),
child: Row(
children: [
Expanded(
child: _ModeSegment(
segmentKey: const Key('auth-mode-sign-in'),
label: l10n.signIn,
hiddenLabel: l10n.authSwitchToSignIn,
selected: !signUpMode,
onTap: busy ? null : () => onSelected(false),
),
),
const SizedBox(width: 4),
Expanded(
child: _ModeSegment(
segmentKey: const Key('auth-mode-sign-up'),
label: l10n.signUp,
hiddenLabel: l10n.authSwitchToSignUp,
selected: signUpMode,
onTap: busy ? null : () => onSelected(true),
),
),
],
),
),
);
}
}