184 lines
5.0 KiB
Dart
184 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.obscurePassword,
|
|
});
|
|
|
|
final bool signUpMode;
|
|
final bool busy;
|
|
final String? errorMessage;
|
|
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.outlineVariantDark,
|
|
width: _cardBorderWidth,
|
|
),
|
|
),
|
|
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.onPrimary,
|
|
fontSize: 25,
|
|
fontWeight: FontWeight.w800,
|
|
height: 1.2,
|
|
),
|
|
),
|
|
const SizedBox(height: 6),
|
|
Text(
|
|
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: Colors.transparent,
|
|
splashFactory: NoSplash.splashFactory,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(22)),
|
|
),
|
|
child: Container(
|
|
height: _minTapTarget,
|
|
padding: const EdgeInsets.all(3),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.bar,
|
|
borderRadius: BorderRadius.circular(22),
|
|
border: Border.all(color: AppColors.outlineVariantDark),
|
|
),
|
|
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),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|