Browse Source

config sign in screen

appflowy 3 years ago
parent
commit
084f939ed0

+ 3 - 3
app_flowy/.vscode/tasks.json

@@ -18,9 +18,9 @@
 			"options": {
 			"options": {
 				"cwd": "${workspaceFolder}/../"
 				"cwd": "${workspaceFolder}/../"
 			  },
 			  },
-			"problemMatcher": [
-                "$rustc"
-            ],
+			// "problemMatcher": [
+            //     "$rustc"
+            // ],
 			"label": "BuildRust"
 			"label": "BuildRust"
 		}
 		}
 	]
 	]

+ 1 - 1
app_flowy/analysis_options.yaml

@@ -15,7 +15,7 @@ analyzer:
     - "**/*.g.dart"
     - "**/*.g.dart"
     - "**/*.freezed.dart"
     - "**/*.freezed.dart"
     - "packages/flowy_editor/**"
     - "packages/flowy_editor/**"
-    - "packages/flowy_infra_ui/**"
+    # - "packages/flowy_infra_ui/**"
     
     
 linter:
 linter:
   # The lint rules applied to this project can be customized in the
   # The lint rules applied to this project can be customized in the

BIN
app_flowy/assets/images/app_flowy_logo.jpg


+ 130 - 3
app_flowy/lib/user/presentation/sign_in/sign_in_screen.dart

@@ -1,8 +1,15 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/user/application/sign_in/sign_in_bloc.dart';
 import 'package:app_flowy/user/application/sign_in/sign_in_bloc.dart';
-import 'package:app_flowy/user/presentation/sign_in/widgets/body.dart';
+import 'package:app_flowy/user/presentation/sign_in/widgets/background.dart';
+import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
+import 'package:flowy_infra_ui/widget/rounded_button.dart';
+import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
+import 'package:flowy_infra_ui/widget/spacing.dart';
+import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:dartz/dartz.dart';
 
 
 class SignInScreen extends StatelessWidget {
 class SignInScreen extends StatelessWidget {
   const SignInScreen({Key? key}) : super(key: key);
   const SignInScreen({Key? key}) : super(key: key);
@@ -11,9 +18,129 @@ class SignInScreen extends StatelessWidget {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     return BlocProvider(
     return BlocProvider(
       create: (context) => getIt<SignInBloc>(),
       create: (context) => getIt<SignInBloc>(),
-      child: const Scaffold(
-        body: Body(),
+      child: Scaffold(
+        body: BlocProvider(
+          create: (context) => getIt<SignInBloc>(),
+          child: BlocConsumer<SignInBloc, SignInState>(
+            listenWhen: (p, c) => p != c,
+            listener: (context, state) {
+              state.signInFailure.fold(
+                () {},
+                (result) => _handleStateErrors(result, context),
+              );
+            },
+            builder: (context, state) => const SignInForm(),
+          ),
+        ),
       ),
       ),
     );
     );
   }
   }
+
+  void _handleStateErrors(
+      Either<UserDetail, UserError> some, BuildContext context) {
+    some.fold(
+      (userDetail) => _showHomeScreen(context, userDetail),
+      (result) => _showErrorMessage(context, result.msg),
+    );
+  }
+
+  void _showErrorMessage(BuildContext context, String msg) {
+    ScaffoldMessenger.of(context).showSnackBar(
+      SnackBar(
+        content: Text(msg),
+      ),
+    );
+  }
+
+  void _showHomeScreen(BuildContext context, UserDetail userDetail) {
+    Navigator.pushReplacement(
+      context,
+      MaterialPageRoute(
+        builder: (context) {
+          return HomeScreen(userDetail);
+        },
+      ),
+    );
+  }
+}
+
+class SignInForm extends StatelessWidget {
+  const SignInForm({
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Align(
+      alignment: Alignment.center,
+      child: SignInFormContainer(
+        children: [
+          const SignInTitle(
+            title: 'Login to Appflowy',
+            logoSize: Size(60, 60),
+          ),
+          const VSpace(30),
+          RoundedInputField(
+            hintText: 'email',
+            onChanged: (value) =>
+                context.read<SignInBloc>().add(SignInEvent.emailChanged(value)),
+          ),
+          RoundedInputField(
+            obscureText: true,
+            hintText: 'password',
+            onChanged: (value) => context
+                .read<SignInBloc>()
+                .add(SignInEvent.passwordChanged(value)),
+          ),
+          TextButton(
+            style: TextButton.styleFrom(
+              textStyle: const TextStyle(fontSize: 12),
+            ),
+            onPressed: () => _showForgetPasswordScreen(context),
+            child: const Text(
+              'Forgot Password?',
+              style: TextStyle(color: Colors.lightBlue),
+            ),
+          ),
+          RoundedButton(
+            title: 'Login',
+            height: 60,
+            borderRadius: BorderRadius.circular(10),
+            color: Colors.lightBlue,
+            press: () {
+              context
+                  .read<SignInBloc>()
+                  .add(const SignInEvent.signedInWithUserEmailAndPassword());
+            },
+          ),
+          const VSpace(10),
+          Row(
+            children: [
+              const Text("Dont't have an account",
+                  style: TextStyle(color: Colors.blueGrey, fontSize: 12)),
+              TextButton(
+                style: TextButton.styleFrom(
+                  textStyle: const TextStyle(fontSize: 12),
+                ),
+                onPressed: () {},
+                child: const Text(
+                  'Sign Up',
+                  style: TextStyle(color: Colors.lightBlue),
+                ),
+              ),
+            ],
+            mainAxisAlignment: MainAxisAlignment.center,
+          ),
+          if (context.read<SignInBloc>().state.isSubmitting) ...[
+            const SizedBox(height: 8),
+            const LinearProgressIndicator(value: null),
+          ]
+        ],
+      ),
+    );
+  }
+
+  void _showForgetPasswordScreen(BuildContext context) {
+    throw UnimplementedError();
+  }
 }
 }

+ 47 - 19
app_flowy/lib/user/presentation/sign_in/widgets/background.dart

@@ -1,29 +1,57 @@
+import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 
 
-class SignInBackground extends StatelessWidget {
-  final Widget child;
-  const SignInBackground({
+class SignInFormContainer extends StatelessWidget {
+  final List<Widget> children;
+  const SignInFormContainer({
     Key? key,
     Key? key,
-    required this.child,
+    required this.children,
   }) : super(key: key);
   }) : super(key: key);
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    var size = MediaQuery.of(context).size;
+    final size = MediaQuery.of(context).size;
     return SizedBox(
     return SizedBox(
-        height: size.height,
-        width: double.infinity,
-        child: Stack(
-          alignment: Alignment.center,
-          children: [
-            Image(
-                fit: BoxFit.cover,
-                width: size.width,
-                height: size.height,
-                image: const AssetImage(
-                    'assets/images/appflowy_launch_splash.jpg')),
-            child,
-          ],
-        ));
+      width: size.width * 0.3,
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: children,
+      ),
+    );
+  }
+}
+
+class SignInTitle extends StatelessWidget {
+  final String title;
+  final Size logoSize;
+  const SignInTitle({
+    Key? key,
+    required this.title,
+    required this.logoSize,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return SizedBox(
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: [
+          Image(
+              fit: BoxFit.cover,
+              width: logoSize.width,
+              height: logoSize.height,
+              image: const AssetImage('assets/images/app_flowy_logo.jpg')),
+          const VSpace(30),
+          Text(
+            title,
+            style: const TextStyle(
+              color: Colors.black,
+              fontWeight: FontWeight.bold,
+              fontSize: 20,
+            ),
+          )
+        ],
+      ),
+    );
   }
   }
 }
 }

+ 0 - 125
app_flowy/lib/user/presentation/sign_in/widgets/body.dart

@@ -1,125 +0,0 @@
-import 'package:app_flowy/startup/startup.dart';
-import 'package:app_flowy/user/application/sign_in/sign_in_bloc.dart';
-import 'package:app_flowy/user/presentation/sign_in/widgets/background.dart';
-import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
-import 'package:dartz/dartz.dart';
-import 'package:flowy_infra_ui/widget/rounded_button.dart';
-import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
-import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-class Body extends StatelessWidget {
-  const Body({Key? key}) : super(key: key);
-  @override
-  Widget build(BuildContext context) {
-    return BlocProvider(
-      create: (context) => getIt<SignInBloc>(),
-      child: const SignInBackground(
-        child: SignInForm(),
-      ),
-    );
-  }
-}
-
-class SignInForm extends StatelessWidget {
-  const SignInForm({
-    Key? key,
-  }) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocConsumer<SignInBloc, SignInState>(
-      listenWhen: (p, c) => p != c,
-      listener: (context, state) {
-        state.signInFailure.fold(
-          () {},
-          (result) => _handleStateErrors(result, context),
-        );
-      },
-      builder: (context, state) {
-        return SignInFormBackground(
-          children: [
-            const SizedBox(height: 30),
-            RoundedInputField(
-              icon: Icons.person,
-              hintText: 'email',
-              onChanged: (value) => context
-                  .read<SignInBloc>()
-                  .add(SignInEvent.emailChanged(value)),
-            ),
-            RoundedInputField(
-              icon: Icons.lock,
-              obscureText: true,
-              hintText: 'password',
-              onChanged: (value) => context
-                  .read<SignInBloc>()
-                  .add(SignInEvent.passwordChanged(value)),
-            ),
-            RoundedButton(
-              title: 'LOGIN',
-              press: () {
-                context
-                    .read<SignInBloc>()
-                    .add(const SignInEvent.signedInWithUserEmailAndPassword());
-              },
-            ),
-            if (state.isSubmitting) ...[
-              const SizedBox(height: 8),
-              const LinearProgressIndicator(value: null),
-            ]
-          ],
-        );
-      },
-    );
-  }
-
-  void _handleStateErrors(
-      Either<UserDetail, UserError> some, BuildContext context) {
-    some.fold(
-      (userDetail) => showHomeScreen(context, userDetail),
-      (result) => _showErrorMessage(context, result.msg),
-    );
-  }
-
-  void _showErrorMessage(BuildContext context, String msg) {
-    ScaffoldMessenger.of(context).showSnackBar(
-      SnackBar(
-        content: Text(msg),
-      ),
-    );
-  }
-
-  void showHomeScreen(BuildContext context, UserDetail userDetail) {
-    Navigator.pushReplacement(
-      context,
-      MaterialPageRoute(
-        builder: (context) {
-          return HomeScreen(userDetail);
-        },
-      ),
-    );
-  }
-}
-
-class SignInFormBackground extends StatelessWidget {
-  final List<Widget> children;
-  const SignInFormBackground({
-    Key? key,
-    required this.children,
-  }) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    final size = MediaQuery.of(context).size;
-
-    return Container(
-      width: size.width * 0.4,
-      alignment: Alignment.center,
-      child: SingleChildScrollView(
-        child: Column(
-            mainAxisAlignment: MainAxisAlignment.center, children: children),
-      ),
-    );
-  }
-}

+ 24 - 7
app_flowy/packages/flowy_infra_ui/lib/widget/rounded_button.dart

@@ -3,13 +3,23 @@ import 'package:flutter/material.dart';
 class RoundedButton extends StatelessWidget {
 class RoundedButton extends StatelessWidget {
   final VoidCallback? press;
   final VoidCallback? press;
   final String? title;
   final String? title;
-  final Size? size;
+  final double? width;
+  final double? height;
+  final BorderRadius borderRadius;
+  final Color borderColor;
+  final Color color;
+  final Color textColor;
 
 
   const RoundedButton({
   const RoundedButton({
     Key? key,
     Key? key,
     this.press,
     this.press,
     this.title,
     this.title,
-    this.size,
+    this.width,
+    this.height,
+    this.borderRadius = BorderRadius.zero,
+    this.borderColor = Colors.transparent,
+    this.color = Colors.transparent,
+    this.textColor = Colors.white,
   }) : super(key: key);
   }) : super(key: key);
 
 
   @override
   @override
@@ -17,15 +27,22 @@ class RoundedButton extends StatelessWidget {
     return ConstrainedBox(
     return ConstrainedBox(
       constraints: BoxConstraints(
       constraints: BoxConstraints(
         minWidth: 100,
         minWidth: 100,
-        maxWidth: size?.width ?? double.infinity,
+        maxWidth: width ?? double.infinity,
         minHeight: 50,
         minHeight: 50,
-        maxHeight: size?.height ?? double.infinity,
+        maxHeight: height ?? 60,
       ),
       ),
       child: Container(
       child: Container(
         margin: const EdgeInsets.symmetric(vertical: 10),
         margin: const EdgeInsets.symmetric(vertical: 10),
-        child: TextButton(
-          child: Text(title ?? ''),
-          onPressed: press,
+        decoration: BoxDecoration(
+          border: Border.all(color: borderColor),
+          borderRadius: borderRadius,
+          color: color,
+        ),
+        child: SizedBox.expand(
+          child: TextButton(
+            child: Text(title ?? '', style: TextStyle(color: textColor)),
+            onPressed: press,
+          ),
         ),
         ),
       ),
       ),
     );
     );

+ 19 - 12
app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart

@@ -10,26 +10,33 @@ class RoundedInputField extends StatelessWidget {
   const RoundedInputField({
   const RoundedInputField({
     Key? key,
     Key? key,
     this.hintText,
     this.hintText,
-    this.icon = Icons.person,
+    this.icon,
     this.obscureText = false,
     this.obscureText = false,
     this.onChanged,
     this.onChanged,
   }) : super(key: key);
   }) : super(key: key);
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
+    final Icon? newIcon = icon == null
+        ? null
+        : Icon(
+            icon!,
+            color: const Color(0xFF6F35A5),
+          );
+
     return TextFieldContainer(
     return TextFieldContainer(
-        child: TextFormField(
-      onChanged: onChanged,
-      cursorColor: const Color(0xFF6F35A5),
-      obscureText: obscureText,
-      decoration: InputDecoration(
-        icon: Icon(
-          icon,
-          color: const Color(0xFF6F35A5),
+      borderRadius: BorderRadius.circular(10),
+      borderColor: Colors.blueGrey,
+      child: TextFormField(
+        onChanged: onChanged,
+        cursorColor: const Color(0xFF6F35A5),
+        obscureText: obscureText,
+        decoration: InputDecoration(
+          icon: newIcon,
+          hintText: hintText,
+          border: InputBorder.none,
         ),
         ),
-        hintText: hintText,
-        border: InputBorder.none,
       ),
       ),
-    ));
+    );
   }
   }
 }
 }

+ 12 - 3
app_flowy/packages/flowy_infra_ui/lib/widget/text_field_container.dart

@@ -3,21 +3,30 @@ import 'package:flutter/material.dart';
 
 
 class TextFieldContainer extends StatelessWidget {
 class TextFieldContainer extends StatelessWidget {
   final Widget child;
   final Widget child;
+  final BorderRadius borderRadius;
+  final Color borderColor;
+  final Size? size;
   const TextFieldContainer({
   const TextFieldContainer({
     Key? key,
     Key? key,
     required this.child,
     required this.child,
+    this.borderRadius = BorderRadius.zero,
+    this.borderColor = Colors.white,
+    this.size,
   }) : super(key: key);
   }) : super(key: key);
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
+    double height = size == null ? 50 : size!.height;
     return Container(
     return Container(
       margin: const EdgeInsets.symmetric(vertical: 10),
       margin: const EdgeInsets.symmetric(vertical: 10),
-      padding: const EdgeInsets.symmetric(horizontal: 20),
+      padding: const EdgeInsets.symmetric(horizontal: 15),
+      height: height,
       decoration: BoxDecoration(
       decoration: BoxDecoration(
+        border: Border.all(color: borderColor),
         color: Colors.white,
         color: Colors.white,
-        borderRadius: BorderRadius.circular(30),
+        borderRadius: borderRadius,
       ),
       ),
-      child: child,
+      child: Align(alignment: Alignment.center, child: child),
     );
     );
   }
   }