Nathan.fooo 61fd608200
Feat/view map database (#1885)
* refactor: rename structs

* chore: read database id from view

* chore: fix open database error because of create a database view for database id

* chore: fix tests

* chore: rename datbase id to view id in flutter

* refactor: move grid and board to database view folder

* refactor: rename functions

* refactor: move calender to datbase view folder

* refactor: rename app_flowy to appflowy_flutter

* chore: reanming

* chore: fix freeze gen

* chore: remove todos

* refactor: view process events

* chore: add link database test

* chore: just open view if there is opened database
2023-02-26 16:27:17 +08:00

213 lines
6.1 KiB
Dart

import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/sign_in_bloc.dart';
import 'package:appflowy/user/presentation/router.dart';
import 'package:appflowy/user/presentation/widgets/background.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/style_widget/text.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_infra_ui/style_widget/snap_bar.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
show UserProfilePB;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_infra/image.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
class SignInScreen extends StatelessWidget {
final AuthRouter router;
const SignInScreen({Key? key, required this.router}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => getIt<SignInBloc>(),
child: BlocListener<SignInBloc, SignInState>(
listener: (context, state) {
state.successOrFail.fold(
() => null,
(result) => _handleSuccessOrFail(result, context),
);
},
child: Scaffold(
body: SignInForm(router: router),
),
),
);
}
void _handleSuccessOrFail(
Either<UserProfilePB, FlowyError> result, BuildContext context) {
result.fold(
(user) => router.pushWelcomeScreen(context, user),
(error) => showSnapBar(context, error.msg),
);
}
}
class SignInForm extends StatelessWidget {
final AuthRouter router;
const SignInForm({
Key? key,
required this.router,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.center,
child: AuthFormContainer(
children: [
FlowyLogoTitle(
title: LocaleKeys.signIn_loginTitle.tr(),
logoSize: const Size(60, 60),
),
const VSpace(30),
const EmailTextField(),
const PasswordTextField(),
ForgetPasswordButton(router: router),
const VSpace(30),
const LoginButton(),
const VSpace(10),
SignUpPrompt(router: router),
if (context.read<SignInBloc>().state.isSubmitting) ...[
const SizedBox(height: 8),
const LinearProgressIndicator(value: null),
]
],
),
);
}
}
class SignUpPrompt extends StatelessWidget {
const SignUpPrompt({
Key? key,
required this.router,
}) : super(key: key);
final AuthRouter router;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlowyText.medium(
LocaleKeys.signIn_dontHaveAnAccount.tr(),
color: Theme.of(context).hintColor,
),
TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.bodyMedium),
onPressed: () => router.pushSignUpScreen(context),
child: Text(
LocaleKeys.signUp_buttonText.tr(),
style: TextStyle(color: Theme.of(context).colorScheme.primary),
),
),
],
);
}
}
class LoginButton extends StatelessWidget {
const LoginButton({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return RoundedTextButton(
title: LocaleKeys.signIn_loginButtonText.tr(),
height: 48,
borderRadius: Corners.s10Border,
onPressed: () => context
.read<SignInBloc>()
.add(const SignInEvent.signedInWithUserEmailAndPassword()),
);
}
}
class ForgetPasswordButton extends StatelessWidget {
const ForgetPasswordButton({
Key? key,
required this.router,
}) : super(key: key);
final AuthRouter router;
@override
Widget build(BuildContext context) {
return TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.bodyMedium),
onPressed: () => router.pushForgetPasswordScreen(context),
child: Text(
LocaleKeys.signIn_forgotPassword.tr(),
style: TextStyle(color: Theme.of(context).colorScheme.primary),
),
);
}
}
class PasswordTextField extends StatelessWidget {
const PasswordTextField({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocBuilder<SignInBloc, SignInState>(
buildWhen: (previous, current) =>
previous.passwordError != current.passwordError,
builder: (context, state) {
return RoundedInputField(
obscureText: true,
obscureIcon: svgWidget("home/hide"),
obscureHideIcon: svgWidget("home/show"),
hintText: LocaleKeys.signIn_passwordHint.tr(),
errorText: context
.read<SignInBloc>()
.state
.passwordError
.fold(() => "", (error) => error),
onChanged: (value) => context
.read<SignInBloc>()
.add(SignInEvent.passwordChanged(value)),
);
},
);
}
}
class EmailTextField extends StatelessWidget {
const EmailTextField({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocBuilder<SignInBloc, SignInState>(
buildWhen: (previous, current) =>
previous.emailError != current.emailError,
builder: (context, state) {
return RoundedInputField(
hintText: LocaleKeys.signIn_emailHint.tr(),
errorText: context
.read<SignInBloc>()
.state
.emailError
.fold(() => "", (error) => error),
onChanged: (value) =>
context.read<SignInBloc>().add(SignInEvent.emailChanged(value)),
);
},
);
}
}