sign_up_screen.dart 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import 'package:app_flowy/startup/startup.dart';
  2. import 'package:app_flowy/user/application/sign_up_bloc.dart';
  3. import 'package:app_flowy/user/presentation/widgets/background.dart';
  4. import 'package:flowy_infra/theme.dart';
  5. import 'package:flowy_infra_ui/widget/rounded_button.dart';
  6. import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
  7. import 'package:flowy_infra_ui/widget/spacing.dart';
  8. import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
  9. import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
  10. import 'package:flutter/material.dart';
  11. import 'package:flutter_bloc/flutter_bloc.dart';
  12. import 'package:dartz/dartz.dart';
  13. import 'package:flowy_infra/image.dart';
  14. class SignUpScreen extends StatelessWidget {
  15. const SignUpScreen({Key? key}) : super(key: key);
  16. @override
  17. Widget build(BuildContext context) {
  18. return BlocProvider(
  19. create: (context) => getIt<SignUpBloc>(),
  20. child: BlocListener<SignUpBloc, SignUpState>(
  21. listener: (context, state) {
  22. state.successOrFail.fold(
  23. () => null,
  24. (result) => _handleSuccessOrFail(result, context),
  25. );
  26. },
  27. child: const Scaffold(
  28. body: SignUpForm(),
  29. ),
  30. ),
  31. );
  32. }
  33. void _handleSuccessOrFail(
  34. Either<UserProfile, UserError> result, BuildContext context) {
  35. result.fold(
  36. (user) => {
  37. // router.showWorkspaceSelectScreen(context, user)
  38. },
  39. (error) => _showErrorMessage(context, error.msg),
  40. );
  41. }
  42. void _showErrorMessage(BuildContext context, String msg) {
  43. ScaffoldMessenger.of(context).showSnackBar(
  44. SnackBar(
  45. content: Text(msg),
  46. ),
  47. );
  48. }
  49. }
  50. class SignUpForm extends StatelessWidget {
  51. const SignUpForm({
  52. Key? key,
  53. }) : super(key: key);
  54. @override
  55. Widget build(BuildContext context) {
  56. return Align(
  57. alignment: Alignment.center,
  58. child: AuthFormContainer(
  59. children: [
  60. const AuthFormTitle(
  61. title: 'Sign Up to Appflowy',
  62. logoSize: Size(60, 60),
  63. ),
  64. const VSpace(30),
  65. const EmailTextField(),
  66. const PasswordTextField(),
  67. const PasswordTextField(hintText: "Repeate password"),
  68. const VSpace(30),
  69. const SignUpButton(),
  70. const VSpace(10),
  71. const SignUpPrompt(),
  72. if (context.read<SignUpBloc>().state.isSubmitting) ...[
  73. const SizedBox(height: 8),
  74. const LinearProgressIndicator(value: null),
  75. ]
  76. ],
  77. ),
  78. );
  79. }
  80. }
  81. class SignUpPrompt extends StatelessWidget {
  82. const SignUpPrompt({
  83. Key? key,
  84. }) : super(key: key);
  85. @override
  86. Widget build(BuildContext context) {
  87. final theme = context.watch<AppTheme>();
  88. return Row(
  89. children: [
  90. Text("Already have an account",
  91. style: TextStyle(color: theme.shader3, fontSize: 12)),
  92. TextButton(
  93. style: TextButton.styleFrom(
  94. textStyle: const TextStyle(fontSize: 12),
  95. ),
  96. onPressed: () => Navigator.pop(context),
  97. child: Text(
  98. 'Sign In',
  99. style: TextStyle(color: theme.main1),
  100. ),
  101. ),
  102. ],
  103. mainAxisAlignment: MainAxisAlignment.center,
  104. );
  105. }
  106. }
  107. class SignUpButton extends StatelessWidget {
  108. const SignUpButton({
  109. Key? key,
  110. }) : super(key: key);
  111. @override
  112. Widget build(BuildContext context) {
  113. final theme = context.watch<AppTheme>();
  114. return RoundedTextButton(
  115. title: 'Get Started',
  116. height: 48,
  117. borderRadius: BorderRadius.circular(10),
  118. color: theme.main1,
  119. press: () {
  120. context
  121. .read<SignUpBloc>()
  122. .add(const SignUpEvent.signUpWithUserEmailAndPassword());
  123. },
  124. );
  125. }
  126. }
  127. class PasswordTextField extends StatelessWidget {
  128. final String hintText;
  129. const PasswordTextField({
  130. Key? key,
  131. this.hintText = "Password",
  132. }) : super(key: key);
  133. @override
  134. Widget build(BuildContext context) {
  135. final theme = context.watch<AppTheme>();
  136. return BlocBuilder<SignUpBloc, SignUpState>(
  137. buildWhen: (previous, current) =>
  138. previous.passwordError != current.passwordError,
  139. builder: (context, state) {
  140. return RoundedInputField(
  141. obscureText: true,
  142. obscureIcon: svgWidgetWithName("home/Hide.svg"),
  143. obscureHideIcon: svgWidgetWithName("home/Show.svg"),
  144. fontSize: 14,
  145. fontWeight: FontWeight.w500,
  146. hintText: hintText,
  147. normalBorderColor: theme.shader4,
  148. highlightBorderColor: theme.red,
  149. errorText: context
  150. .read<SignUpBloc>()
  151. .state
  152. .passwordError
  153. .fold(() => "", (error) => error),
  154. onChanged: (value) => context
  155. .read<SignUpBloc>()
  156. .add(SignUpEvent.passwordChanged(value)),
  157. );
  158. },
  159. );
  160. }
  161. }
  162. class EmailTextField extends StatelessWidget {
  163. const EmailTextField({
  164. Key? key,
  165. }) : super(key: key);
  166. @override
  167. Widget build(BuildContext context) {
  168. final theme = context.watch<AppTheme>();
  169. return BlocBuilder<SignUpBloc, SignUpState>(
  170. buildWhen: (previous, current) =>
  171. previous.emailError != current.emailError,
  172. builder: (context, state) {
  173. return RoundedInputField(
  174. hintText: 'Email',
  175. normalBorderColor: theme.shader4,
  176. highlightBorderColor: theme.red,
  177. errorText: context
  178. .read<SignUpBloc>()
  179. .state
  180. .emailError
  181. .fold(() => "", (error) => error),
  182. onChanged: (value) =>
  183. context.read<SignUpBloc>().add(SignUpEvent.emailChanged(value)),
  184. );
  185. },
  186. );
  187. }
  188. }