mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-24 22:57:12 -04:00
config sign up
This commit is contained in:
parent
835ace5da0
commit
85e3e07cbf
14 changed files with 1042 additions and 63 deletions
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
@ -2,7 +2,6 @@ import 'package:app_flowy/user/domain/i_auth.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
|
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
// ignore: import_of_legacy_library_into_null_safe
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
part 'sign_in_bloc.freezed.dart';
|
part 'sign_in_bloc.freezed.dart';
|
||||||
|
@ -35,8 +34,8 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
|
||||||
|
|
||||||
final result = await authImpl.signIn(state.email, state.password);
|
final result = await authImpl.signIn(state.email, state.password);
|
||||||
yield result.fold(
|
yield result.fold(
|
||||||
(UserProfile) => state.copyWith(
|
(userProfile) => state.copyWith(
|
||||||
isSubmitting: false, successOrFail: some(left(UserProfile))),
|
isSubmitting: false, successOrFail: some(left(userProfile))),
|
||||||
(error) => stateFromCode(error),
|
(error) => stateFromCode(error),
|
||||||
);
|
);
|
||||||
}
|
}
|
87
app_flowy/lib/user/application/sign_up_bloc.dart
Normal file
87
app_flowy/lib/user/application/sign_up_bloc.dart
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import 'package:app_flowy/user/domain/i_auth.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
part 'sign_up_bloc.freezed.dart';
|
||||||
|
|
||||||
|
class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
|
||||||
|
final IAuth authImpl;
|
||||||
|
SignUpBloc(this.authImpl) : super(SignUpState.initial());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<SignUpState> mapEventToState(
|
||||||
|
SignUpEvent event,
|
||||||
|
) async* {
|
||||||
|
yield* event.map(
|
||||||
|
signUpWithUserEmailAndPassword: (e) async* {
|
||||||
|
yield* _performActionOnSignUp(
|
||||||
|
state,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
emailChanged: (EmailChanged value) async* {
|
||||||
|
yield state.copyWith(email: value.email, successOrFail: none());
|
||||||
|
},
|
||||||
|
passwordChanged: (PasswordChanged value) async* {
|
||||||
|
yield state.copyWith(password: value.password, successOrFail: none());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<SignUpState> _performActionOnSignUp(SignUpState state) async* {
|
||||||
|
yield state.copyWith(isSubmitting: true);
|
||||||
|
|
||||||
|
final result = await authImpl.signIn(state.email, state.password);
|
||||||
|
yield result.fold(
|
||||||
|
(userProfile) => state.copyWith(
|
||||||
|
isSubmitting: false, successOrFail: some(left(userProfile))),
|
||||||
|
(error) => stateFromCode(error),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SignUpState stateFromCode(UserError error) {
|
||||||
|
switch (error.code) {
|
||||||
|
case ErrorCode.EmailFormatInvalid:
|
||||||
|
return state.copyWith(
|
||||||
|
isSubmitting: false,
|
||||||
|
emailError: some(error.msg),
|
||||||
|
passwordError: none());
|
||||||
|
case ErrorCode.PasswordFormatInvalid:
|
||||||
|
return state.copyWith(
|
||||||
|
isSubmitting: false,
|
||||||
|
passwordError: some(error.msg),
|
||||||
|
emailError: none());
|
||||||
|
default:
|
||||||
|
return state.copyWith(
|
||||||
|
isSubmitting: false, successOrFail: some(right(error)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class SignUpEvent with _$SignUpEvent {
|
||||||
|
const factory SignUpEvent.signUpWithUserEmailAndPassword() =
|
||||||
|
SignUpWithUserEmailAndPassword;
|
||||||
|
const factory SignUpEvent.emailChanged(String email) = EmailChanged;
|
||||||
|
const factory SignUpEvent.passwordChanged(String password) = PasswordChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class SignUpState with _$SignUpState {
|
||||||
|
const factory SignUpState({
|
||||||
|
String? email,
|
||||||
|
String? password,
|
||||||
|
required bool isSubmitting,
|
||||||
|
required Option<String> passwordError,
|
||||||
|
required Option<String> emailError,
|
||||||
|
required Option<Either<UserProfile, UserError>> successOrFail,
|
||||||
|
}) = _SignUpState;
|
||||||
|
|
||||||
|
factory SignUpState.initial() => SignUpState(
|
||||||
|
isSubmitting: false,
|
||||||
|
passwordError: none(),
|
||||||
|
emailError: none(),
|
||||||
|
successOrFail: none(),
|
||||||
|
);
|
||||||
|
}
|
691
app_flowy/lib/user/application/sign_up_bloc.freezed.dart
Normal file
691
app_flowy/lib/user/application/sign_up_bloc.freezed.dart
Normal file
|
@ -0,0 +1,691 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
|
||||||
|
|
||||||
|
part of 'sign_up_bloc.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SignUpEventTearOff {
|
||||||
|
const _$SignUpEventTearOff();
|
||||||
|
|
||||||
|
SignUpWithUserEmailAndPassword signUpWithUserEmailAndPassword() {
|
||||||
|
return const SignUpWithUserEmailAndPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmailChanged emailChanged(String email) {
|
||||||
|
return EmailChanged(
|
||||||
|
email,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PasswordChanged passwordChanged(String password) {
|
||||||
|
return PasswordChanged(
|
||||||
|
password,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
const $SignUpEvent = _$SignUpEventTearOff();
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SignUpEvent {
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function() signUpWithUserEmailAndPassword,
|
||||||
|
required TResult Function(String email) emailChanged,
|
||||||
|
required TResult Function(String password) passwordChanged,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function()? signUpWithUserEmailAndPassword,
|
||||||
|
TResult Function(String email)? emailChanged,
|
||||||
|
TResult Function(String password)? passwordChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(SignUpWithUserEmailAndPassword value)
|
||||||
|
signUpWithUserEmailAndPassword,
|
||||||
|
required TResult Function(EmailChanged value) emailChanged,
|
||||||
|
required TResult Function(PasswordChanged value) passwordChanged,
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(SignUpWithUserEmailAndPassword value)?
|
||||||
|
signUpWithUserEmailAndPassword,
|
||||||
|
TResult Function(EmailChanged value)? emailChanged,
|
||||||
|
TResult Function(PasswordChanged value)? passwordChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SignUpEventCopyWith<$Res> {
|
||||||
|
factory $SignUpEventCopyWith(
|
||||||
|
SignUpEvent value, $Res Function(SignUpEvent) then) =
|
||||||
|
_$SignUpEventCopyWithImpl<$Res>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SignUpEventCopyWithImpl<$Res> implements $SignUpEventCopyWith<$Res> {
|
||||||
|
_$SignUpEventCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
final SignUpEvent _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function(SignUpEvent) _then;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SignUpWithUserEmailAndPasswordCopyWith<$Res> {
|
||||||
|
factory $SignUpWithUserEmailAndPasswordCopyWith(
|
||||||
|
SignUpWithUserEmailAndPassword value,
|
||||||
|
$Res Function(SignUpWithUserEmailAndPassword) then) =
|
||||||
|
_$SignUpWithUserEmailAndPasswordCopyWithImpl<$Res>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SignUpWithUserEmailAndPasswordCopyWithImpl<$Res>
|
||||||
|
extends _$SignUpEventCopyWithImpl<$Res>
|
||||||
|
implements $SignUpWithUserEmailAndPasswordCopyWith<$Res> {
|
||||||
|
_$SignUpWithUserEmailAndPasswordCopyWithImpl(
|
||||||
|
SignUpWithUserEmailAndPassword _value,
|
||||||
|
$Res Function(SignUpWithUserEmailAndPassword) _then)
|
||||||
|
: super(_value, (v) => _then(v as SignUpWithUserEmailAndPassword));
|
||||||
|
|
||||||
|
@override
|
||||||
|
SignUpWithUserEmailAndPassword get _value =>
|
||||||
|
super._value as SignUpWithUserEmailAndPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$SignUpWithUserEmailAndPassword
|
||||||
|
implements SignUpWithUserEmailAndPassword {
|
||||||
|
const _$SignUpWithUserEmailAndPassword();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SignUpEvent.signUpWithUserEmailAndPassword()';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(dynamic other) {
|
||||||
|
return identical(this, other) || (other is SignUpWithUserEmailAndPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function() signUpWithUserEmailAndPassword,
|
||||||
|
required TResult Function(String email) emailChanged,
|
||||||
|
required TResult Function(String password) passwordChanged,
|
||||||
|
}) {
|
||||||
|
return signUpWithUserEmailAndPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function()? signUpWithUserEmailAndPassword,
|
||||||
|
TResult Function(String email)? emailChanged,
|
||||||
|
TResult Function(String password)? passwordChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (signUpWithUserEmailAndPassword != null) {
|
||||||
|
return signUpWithUserEmailAndPassword();
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(SignUpWithUserEmailAndPassword value)
|
||||||
|
signUpWithUserEmailAndPassword,
|
||||||
|
required TResult Function(EmailChanged value) emailChanged,
|
||||||
|
required TResult Function(PasswordChanged value) passwordChanged,
|
||||||
|
}) {
|
||||||
|
return signUpWithUserEmailAndPassword(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(SignUpWithUserEmailAndPassword value)?
|
||||||
|
signUpWithUserEmailAndPassword,
|
||||||
|
TResult Function(EmailChanged value)? emailChanged,
|
||||||
|
TResult Function(PasswordChanged value)? passwordChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (signUpWithUserEmailAndPassword != null) {
|
||||||
|
return signUpWithUserEmailAndPassword(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class SignUpWithUserEmailAndPassword implements SignUpEvent {
|
||||||
|
const factory SignUpWithUserEmailAndPassword() =
|
||||||
|
_$SignUpWithUserEmailAndPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $EmailChangedCopyWith<$Res> {
|
||||||
|
factory $EmailChangedCopyWith(
|
||||||
|
EmailChanged value, $Res Function(EmailChanged) then) =
|
||||||
|
_$EmailChangedCopyWithImpl<$Res>;
|
||||||
|
$Res call({String email});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$EmailChangedCopyWithImpl<$Res> extends _$SignUpEventCopyWithImpl<$Res>
|
||||||
|
implements $EmailChangedCopyWith<$Res> {
|
||||||
|
_$EmailChangedCopyWithImpl(
|
||||||
|
EmailChanged _value, $Res Function(EmailChanged) _then)
|
||||||
|
: super(_value, (v) => _then(v as EmailChanged));
|
||||||
|
|
||||||
|
@override
|
||||||
|
EmailChanged get _value => super._value as EmailChanged;
|
||||||
|
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? email = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(EmailChanged(
|
||||||
|
email == freezed
|
||||||
|
? _value.email
|
||||||
|
: email // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$EmailChanged implements EmailChanged {
|
||||||
|
const _$EmailChanged(this.email);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String email;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SignUpEvent.emailChanged(email: $email)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(dynamic other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other is EmailChanged &&
|
||||||
|
(identical(other.email, email) ||
|
||||||
|
const DeepCollectionEquality().equals(other.email, email)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
runtimeType.hashCode ^ const DeepCollectionEquality().hash(email);
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
$EmailChangedCopyWith<EmailChanged> get copyWith =>
|
||||||
|
_$EmailChangedCopyWithImpl<EmailChanged>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function() signUpWithUserEmailAndPassword,
|
||||||
|
required TResult Function(String email) emailChanged,
|
||||||
|
required TResult Function(String password) passwordChanged,
|
||||||
|
}) {
|
||||||
|
return emailChanged(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function()? signUpWithUserEmailAndPassword,
|
||||||
|
TResult Function(String email)? emailChanged,
|
||||||
|
TResult Function(String password)? passwordChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (emailChanged != null) {
|
||||||
|
return emailChanged(email);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(SignUpWithUserEmailAndPassword value)
|
||||||
|
signUpWithUserEmailAndPassword,
|
||||||
|
required TResult Function(EmailChanged value) emailChanged,
|
||||||
|
required TResult Function(PasswordChanged value) passwordChanged,
|
||||||
|
}) {
|
||||||
|
return emailChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(SignUpWithUserEmailAndPassword value)?
|
||||||
|
signUpWithUserEmailAndPassword,
|
||||||
|
TResult Function(EmailChanged value)? emailChanged,
|
||||||
|
TResult Function(PasswordChanged value)? passwordChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (emailChanged != null) {
|
||||||
|
return emailChanged(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class EmailChanged implements SignUpEvent {
|
||||||
|
const factory EmailChanged(String email) = _$EmailChanged;
|
||||||
|
|
||||||
|
String get email => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
$EmailChangedCopyWith<EmailChanged> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $PasswordChangedCopyWith<$Res> {
|
||||||
|
factory $PasswordChangedCopyWith(
|
||||||
|
PasswordChanged value, $Res Function(PasswordChanged) then) =
|
||||||
|
_$PasswordChangedCopyWithImpl<$Res>;
|
||||||
|
$Res call({String password});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$PasswordChangedCopyWithImpl<$Res>
|
||||||
|
extends _$SignUpEventCopyWithImpl<$Res>
|
||||||
|
implements $PasswordChangedCopyWith<$Res> {
|
||||||
|
_$PasswordChangedCopyWithImpl(
|
||||||
|
PasswordChanged _value, $Res Function(PasswordChanged) _then)
|
||||||
|
: super(_value, (v) => _then(v as PasswordChanged));
|
||||||
|
|
||||||
|
@override
|
||||||
|
PasswordChanged get _value => super._value as PasswordChanged;
|
||||||
|
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? password = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(PasswordChanged(
|
||||||
|
password == freezed
|
||||||
|
? _value.password
|
||||||
|
: password // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$PasswordChanged implements PasswordChanged {
|
||||||
|
const _$PasswordChanged(this.password);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String password;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SignUpEvent.passwordChanged(password: $password)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(dynamic other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other is PasswordChanged &&
|
||||||
|
(identical(other.password, password) ||
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other.password, password)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
runtimeType.hashCode ^ const DeepCollectionEquality().hash(password);
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
$PasswordChangedCopyWith<PasswordChanged> get copyWith =>
|
||||||
|
_$PasswordChangedCopyWithImpl<PasswordChanged>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function() signUpWithUserEmailAndPassword,
|
||||||
|
required TResult Function(String email) emailChanged,
|
||||||
|
required TResult Function(String password) passwordChanged,
|
||||||
|
}) {
|
||||||
|
return passwordChanged(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function()? signUpWithUserEmailAndPassword,
|
||||||
|
TResult Function(String email)? emailChanged,
|
||||||
|
TResult Function(String password)? passwordChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (passwordChanged != null) {
|
||||||
|
return passwordChanged(password);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(SignUpWithUserEmailAndPassword value)
|
||||||
|
signUpWithUserEmailAndPassword,
|
||||||
|
required TResult Function(EmailChanged value) emailChanged,
|
||||||
|
required TResult Function(PasswordChanged value) passwordChanged,
|
||||||
|
}) {
|
||||||
|
return passwordChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(SignUpWithUserEmailAndPassword value)?
|
||||||
|
signUpWithUserEmailAndPassword,
|
||||||
|
TResult Function(EmailChanged value)? emailChanged,
|
||||||
|
TResult Function(PasswordChanged value)? passwordChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (passwordChanged != null) {
|
||||||
|
return passwordChanged(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PasswordChanged implements SignUpEvent {
|
||||||
|
const factory PasswordChanged(String password) = _$PasswordChanged;
|
||||||
|
|
||||||
|
String get password => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
$PasswordChangedCopyWith<PasswordChanged> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SignUpStateTearOff {
|
||||||
|
const _$SignUpStateTearOff();
|
||||||
|
|
||||||
|
_SignUpState call(
|
||||||
|
{String? email,
|
||||||
|
String? password,
|
||||||
|
required bool isSubmitting,
|
||||||
|
required Option<String> passwordError,
|
||||||
|
required Option<String> emailError,
|
||||||
|
required Option<Either<UserProfile, UserError>> successOrFail}) {
|
||||||
|
return _SignUpState(
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
isSubmitting: isSubmitting,
|
||||||
|
passwordError: passwordError,
|
||||||
|
emailError: emailError,
|
||||||
|
successOrFail: successOrFail,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
const $SignUpState = _$SignUpStateTearOff();
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SignUpState {
|
||||||
|
String? get email => throw _privateConstructorUsedError;
|
||||||
|
String? get password => throw _privateConstructorUsedError;
|
||||||
|
bool get isSubmitting => throw _privateConstructorUsedError;
|
||||||
|
Option<String> get passwordError => throw _privateConstructorUsedError;
|
||||||
|
Option<String> get emailError => throw _privateConstructorUsedError;
|
||||||
|
Option<Either<UserProfile, UserError>> get successOrFail =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
$SignUpStateCopyWith<SignUpState> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $SignUpStateCopyWith<$Res> {
|
||||||
|
factory $SignUpStateCopyWith(
|
||||||
|
SignUpState value, $Res Function(SignUpState) then) =
|
||||||
|
_$SignUpStateCopyWithImpl<$Res>;
|
||||||
|
$Res call(
|
||||||
|
{String? email,
|
||||||
|
String? password,
|
||||||
|
bool isSubmitting,
|
||||||
|
Option<String> passwordError,
|
||||||
|
Option<String> emailError,
|
||||||
|
Option<Either<UserProfile, UserError>> successOrFail});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$SignUpStateCopyWithImpl<$Res> implements $SignUpStateCopyWith<$Res> {
|
||||||
|
_$SignUpStateCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
final SignUpState _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function(SignUpState) _then;
|
||||||
|
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? email = freezed,
|
||||||
|
Object? password = freezed,
|
||||||
|
Object? isSubmitting = freezed,
|
||||||
|
Object? passwordError = freezed,
|
||||||
|
Object? emailError = freezed,
|
||||||
|
Object? successOrFail = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
email: email == freezed
|
||||||
|
? _value.email
|
||||||
|
: email // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
password: password == freezed
|
||||||
|
? _value.password
|
||||||
|
: password // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
isSubmitting: isSubmitting == freezed
|
||||||
|
? _value.isSubmitting
|
||||||
|
: isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
passwordError: passwordError == freezed
|
||||||
|
? _value.passwordError
|
||||||
|
: passwordError // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<String>,
|
||||||
|
emailError: emailError == freezed
|
||||||
|
? _value.emailError
|
||||||
|
: emailError // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<String>,
|
||||||
|
successOrFail: successOrFail == freezed
|
||||||
|
? _value.successOrFail
|
||||||
|
: successOrFail // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<UserProfile, UserError>>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$SignUpStateCopyWith<$Res>
|
||||||
|
implements $SignUpStateCopyWith<$Res> {
|
||||||
|
factory _$SignUpStateCopyWith(
|
||||||
|
_SignUpState value, $Res Function(_SignUpState) then) =
|
||||||
|
__$SignUpStateCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
$Res call(
|
||||||
|
{String? email,
|
||||||
|
String? password,
|
||||||
|
bool isSubmitting,
|
||||||
|
Option<String> passwordError,
|
||||||
|
Option<String> emailError,
|
||||||
|
Option<Either<UserProfile, UserError>> successOrFail});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$SignUpStateCopyWithImpl<$Res> extends _$SignUpStateCopyWithImpl<$Res>
|
||||||
|
implements _$SignUpStateCopyWith<$Res> {
|
||||||
|
__$SignUpStateCopyWithImpl(
|
||||||
|
_SignUpState _value, $Res Function(_SignUpState) _then)
|
||||||
|
: super(_value, (v) => _then(v as _SignUpState));
|
||||||
|
|
||||||
|
@override
|
||||||
|
_SignUpState get _value => super._value as _SignUpState;
|
||||||
|
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? email = freezed,
|
||||||
|
Object? password = freezed,
|
||||||
|
Object? isSubmitting = freezed,
|
||||||
|
Object? passwordError = freezed,
|
||||||
|
Object? emailError = freezed,
|
||||||
|
Object? successOrFail = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(_SignUpState(
|
||||||
|
email: email == freezed
|
||||||
|
? _value.email
|
||||||
|
: email // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
password: password == freezed
|
||||||
|
? _value.password
|
||||||
|
: password // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
isSubmitting: isSubmitting == freezed
|
||||||
|
? _value.isSubmitting
|
||||||
|
: isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
passwordError: passwordError == freezed
|
||||||
|
? _value.passwordError
|
||||||
|
: passwordError // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<String>,
|
||||||
|
emailError: emailError == freezed
|
||||||
|
? _value.emailError
|
||||||
|
: emailError // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<String>,
|
||||||
|
successOrFail: successOrFail == freezed
|
||||||
|
? _value.successOrFail
|
||||||
|
: successOrFail // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<UserProfile, UserError>>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$_SignUpState implements _SignUpState {
|
||||||
|
const _$_SignUpState(
|
||||||
|
{this.email,
|
||||||
|
this.password,
|
||||||
|
required this.isSubmitting,
|
||||||
|
required this.passwordError,
|
||||||
|
required this.emailError,
|
||||||
|
required this.successOrFail});
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String? email;
|
||||||
|
@override
|
||||||
|
final String? password;
|
||||||
|
@override
|
||||||
|
final bool isSubmitting;
|
||||||
|
@override
|
||||||
|
final Option<String> passwordError;
|
||||||
|
@override
|
||||||
|
final Option<String> emailError;
|
||||||
|
@override
|
||||||
|
final Option<Either<UserProfile, UserError>> successOrFail;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SignUpState(email: $email, password: $password, isSubmitting: $isSubmitting, passwordError: $passwordError, emailError: $emailError, successOrFail: $successOrFail)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(dynamic other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other is _SignUpState &&
|
||||||
|
(identical(other.email, email) ||
|
||||||
|
const DeepCollectionEquality().equals(other.email, email)) &&
|
||||||
|
(identical(other.password, password) ||
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other.password, password)) &&
|
||||||
|
(identical(other.isSubmitting, isSubmitting) ||
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other.isSubmitting, isSubmitting)) &&
|
||||||
|
(identical(other.passwordError, passwordError) ||
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other.passwordError, passwordError)) &&
|
||||||
|
(identical(other.emailError, emailError) ||
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other.emailError, emailError)) &&
|
||||||
|
(identical(other.successOrFail, successOrFail) ||
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other.successOrFail, successOrFail)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
runtimeType.hashCode ^
|
||||||
|
const DeepCollectionEquality().hash(email) ^
|
||||||
|
const DeepCollectionEquality().hash(password) ^
|
||||||
|
const DeepCollectionEquality().hash(isSubmitting) ^
|
||||||
|
const DeepCollectionEquality().hash(passwordError) ^
|
||||||
|
const DeepCollectionEquality().hash(emailError) ^
|
||||||
|
const DeepCollectionEquality().hash(successOrFail);
|
||||||
|
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
@override
|
||||||
|
_$SignUpStateCopyWith<_SignUpState> get copyWith =>
|
||||||
|
__$SignUpStateCopyWithImpl<_SignUpState>(this, _$identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _SignUpState implements SignUpState {
|
||||||
|
const factory _SignUpState(
|
||||||
|
{String? email,
|
||||||
|
String? password,
|
||||||
|
required bool isSubmitting,
|
||||||
|
required Option<String> passwordError,
|
||||||
|
required Option<String> emailError,
|
||||||
|
required Option<Either<UserProfile, UserError>> successOrFail}) =
|
||||||
|
_$_SignUpState;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get email => throw _privateConstructorUsedError;
|
||||||
|
@override
|
||||||
|
String? get password => throw _privateConstructorUsedError;
|
||||||
|
@override
|
||||||
|
bool get isSubmitting => throw _privateConstructorUsedError;
|
||||||
|
@override
|
||||||
|
Option<String> get passwordError => throw _privateConstructorUsedError;
|
||||||
|
@override
|
||||||
|
Option<String> get emailError => throw _privateConstructorUsedError;
|
||||||
|
@override
|
||||||
|
Option<Either<UserProfile, UserError>> get successOrFail =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
@override
|
||||||
|
@JsonKey(ignore: true)
|
||||||
|
_$SignUpStateCopyWith<_SignUpState> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:app_flowy/user/application/sign_in/sign_in_bloc.dart';
|
import 'package:app_flowy/user/application/sign_in_bloc.dart';
|
||||||
|
import 'package:app_flowy/user/application/sign_up_bloc.dart';
|
||||||
import 'package:app_flowy/user/domain/i_auth.dart';
|
import 'package:app_flowy/user/domain/i_auth.dart';
|
||||||
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
|
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
|
||||||
import 'package:app_flowy/user/infrastructure/i_auth_impl.dart';
|
import 'package:app_flowy/user/infrastructure/i_auth_impl.dart';
|
||||||
|
@ -14,5 +15,6 @@ class UserDepsResolver {
|
||||||
|
|
||||||
//Bloc
|
//Bloc
|
||||||
getIt.registerFactory<SignInBloc>(() => SignInBloc(getIt<IAuth>()));
|
getIt.registerFactory<SignInBloc>(() => SignInBloc(getIt<IAuth>()));
|
||||||
|
getIt.registerFactory<SignUpBloc>(() => SignUpBloc(getIt<IAuth>()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:app_flowy/user/presentation/sign_up/sign_up_screen.dart';
|
||||||
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
|
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/workspace/workspace_select_screen.dart';
|
import 'package:app_flowy/workspace/presentation/workspace/workspace_select_screen.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
|
@ -50,6 +51,10 @@ class AuthRouterImpl extends IAuthRouter {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void showSignUpScreen(BuildContext context) {
|
void showSignUpScreen(BuildContext context) {
|
||||||
// TODO: implement showSignUpScreen
|
Navigator.of(context).push(
|
||||||
|
PageRoutes.fade(
|
||||||
|
() => const SignUpScreen(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
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_bloc.dart';
|
||||||
import 'package:app_flowy/user/domain/i_auth.dart';
|
import 'package:app_flowy/user/domain/i_auth.dart';
|
||||||
import 'package:app_flowy/user/presentation/sign_in/widgets/background.dart';
|
import 'package:app_flowy/user/presentation/sign_in/widgets/background.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
|
@ -63,9 +63,9 @@ class SignInForm extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Align(
|
return Align(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: SignInFormContainer(
|
child: AuthFormContainer(
|
||||||
children: [
|
children: [
|
||||||
const SignInTitle(
|
const AuthFormTitle(
|
||||||
title: 'Login to Appflowy',
|
title: 'Login to Appflowy',
|
||||||
logoSize: Size(60, 60),
|
logoSize: Size(60, 60),
|
||||||
),
|
),
|
||||||
|
@ -128,7 +128,7 @@ class LoginButton extends StatelessWidget {
|
||||||
final theme = context.watch<AppTheme>();
|
final theme = context.watch<AppTheme>();
|
||||||
return RoundedTextButton(
|
return RoundedTextButton(
|
||||||
title: 'Login',
|
title: 'Login',
|
||||||
height: 45,
|
height: 48,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
color: theme.main1,
|
color: theme.main1,
|
||||||
press: () {
|
press: () {
|
||||||
|
@ -180,7 +180,7 @@ class PasswordTextField extends StatelessWidget {
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
obscureIcon: svgWidgetWithName("home/Hide.svg"),
|
obscureIcon: svgWidgetWithName("home/Hide.svg"),
|
||||||
obscureHideIcon: svgWidgetWithName("home/Show.svg"),
|
obscureHideIcon: svgWidgetWithName("home/Show.svg"),
|
||||||
hintText: 'password',
|
hintText: 'Password',
|
||||||
normalBorderColor: theme.shader4,
|
normalBorderColor: theme.shader4,
|
||||||
highlightBorderColor: theme.red,
|
highlightBorderColor: theme.red,
|
||||||
errorText: context
|
errorText: context
|
||||||
|
@ -210,7 +210,7 @@ class EmailTextField extends StatelessWidget {
|
||||||
previous.emailError != current.emailError,
|
previous.emailError != current.emailError,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return RoundedInputField(
|
return RoundedInputField(
|
||||||
hintText: 'email',
|
hintText: 'Email',
|
||||||
normalBorderColor: theme.shader4,
|
normalBorderColor: theme.shader4,
|
||||||
highlightBorderColor: theme.red,
|
highlightBorderColor: theme.red,
|
||||||
errorText: context
|
errorText: context
|
202
app_flowy/lib/user/presentation/sign_up_screen.dart
Normal file
202
app_flowy/lib/user/presentation/sign_up_screen.dart
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
|
import 'package:app_flowy/user/application/sign_up_bloc.dart';
|
||||||
|
import 'package:app_flowy/user/presentation/widgets/background.dart';
|
||||||
|
import 'package:flowy_infra/theme.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_profile.pb.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:flowy_infra/image.dart';
|
||||||
|
|
||||||
|
class SignUpScreen extends StatelessWidget {
|
||||||
|
const SignUpScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => getIt<SignUpBloc>(),
|
||||||
|
child: BlocListener<SignUpBloc, SignUpState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
state.successOrFail.fold(
|
||||||
|
() => null,
|
||||||
|
(result) => _handleSuccessOrFail(result, context),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Scaffold(
|
||||||
|
body: SignUpForm(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleSuccessOrFail(
|
||||||
|
Either<UserProfile, UserError> result, BuildContext context) {
|
||||||
|
result.fold(
|
||||||
|
(user) => {
|
||||||
|
// router.showWorkspaceSelectScreen(context, user)
|
||||||
|
},
|
||||||
|
(error) => _showErrorMessage(context, error.msg),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showErrorMessage(BuildContext context, String msg) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(msg),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SignUpForm extends StatelessWidget {
|
||||||
|
const SignUpForm({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: AuthFormContainer(
|
||||||
|
children: [
|
||||||
|
const AuthFormTitle(
|
||||||
|
title: 'Sign Up to Appflowy',
|
||||||
|
logoSize: Size(60, 60),
|
||||||
|
),
|
||||||
|
const VSpace(30),
|
||||||
|
const EmailTextField(),
|
||||||
|
const PasswordTextField(),
|
||||||
|
const PasswordTextField(hintText: "Repeate password"),
|
||||||
|
const VSpace(30),
|
||||||
|
const SignUpButton(),
|
||||||
|
const VSpace(10),
|
||||||
|
const SignUpPrompt(),
|
||||||
|
if (context.read<SignUpBloc>().state.isSubmitting) ...[
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
const LinearProgressIndicator(value: null),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SignUpPrompt extends StatelessWidget {
|
||||||
|
const SignUpPrompt({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Text("Already have an account",
|
||||||
|
style: TextStyle(color: theme.shader3, fontSize: 12)),
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
textStyle: const TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text(
|
||||||
|
'Sign In',
|
||||||
|
style: TextStyle(color: theme.main1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SignUpButton extends StatelessWidget {
|
||||||
|
const SignUpButton({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
|
return RoundedTextButton(
|
||||||
|
title: 'Get Started',
|
||||||
|
height: 48,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
color: theme.main1,
|
||||||
|
press: () {
|
||||||
|
context
|
||||||
|
.read<SignUpBloc>()
|
||||||
|
.add(const SignUpEvent.signUpWithUserEmailAndPassword());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PasswordTextField extends StatelessWidget {
|
||||||
|
final String hintText;
|
||||||
|
const PasswordTextField({
|
||||||
|
Key? key,
|
||||||
|
this.hintText = "Password",
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
|
return BlocBuilder<SignUpBloc, SignUpState>(
|
||||||
|
buildWhen: (previous, current) =>
|
||||||
|
previous.passwordError != current.passwordError,
|
||||||
|
builder: (context, state) {
|
||||||
|
return RoundedInputField(
|
||||||
|
obscureText: true,
|
||||||
|
obscureIcon: svgWidgetWithName("home/Hide.svg"),
|
||||||
|
obscureHideIcon: svgWidgetWithName("home/Show.svg"),
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
hintText: hintText,
|
||||||
|
normalBorderColor: theme.shader4,
|
||||||
|
highlightBorderColor: theme.red,
|
||||||
|
errorText: context
|
||||||
|
.read<SignUpBloc>()
|
||||||
|
.state
|
||||||
|
.passwordError
|
||||||
|
.fold(() => "", (error) => error),
|
||||||
|
onChanged: (value) => context
|
||||||
|
.read<SignUpBloc>()
|
||||||
|
.add(SignUpEvent.passwordChanged(value)),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmailTextField extends StatelessWidget {
|
||||||
|
const EmailTextField({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
|
return BlocBuilder<SignUpBloc, SignUpState>(
|
||||||
|
buildWhen: (previous, current) =>
|
||||||
|
previous.emailError != current.emailError,
|
||||||
|
builder: (context, state) {
|
||||||
|
return RoundedInputField(
|
||||||
|
hintText: 'Email',
|
||||||
|
normalBorderColor: theme.shader4,
|
||||||
|
highlightBorderColor: theme.red,
|
||||||
|
errorText: context
|
||||||
|
.read<SignUpBloc>()
|
||||||
|
.state
|
||||||
|
.emailError
|
||||||
|
.fold(() => "", (error) => error),
|
||||||
|
onChanged: (value) =>
|
||||||
|
context.read<SignUpBloc>().add(SignUpEvent.emailChanged(value)),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,14 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class SignInFormContainer extends StatelessWidget {
|
class AuthFormContainer extends StatelessWidget {
|
||||||
final List<Widget> children;
|
final List<Widget> children;
|
||||||
const SignInFormContainer({
|
const AuthFormContainer({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.children,
|
required this.children,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
@ -15,7 +17,7 @@ class SignInFormContainer extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final size = MediaQuery.of(context).size;
|
final size = MediaQuery.of(context).size;
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: size.width * 0.3,
|
width: min(size.width, 340),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: children,
|
children: children,
|
||||||
|
@ -24,10 +26,10 @@ class SignInFormContainer extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignInTitle extends StatelessWidget {
|
class AuthFormTitle extends StatelessWidget {
|
||||||
final String title;
|
final String title;
|
||||||
final Size logoSize;
|
final Size logoSize;
|
||||||
const SignInTitle({
|
const AuthFormTitle({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.logoSize,
|
required this.logoSize,
|
||||||
|
@ -40,7 +42,10 @@ class SignInTitle extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
svgWidgetWithName("small_logo.svg"),
|
SizedBox.fromSize(
|
||||||
|
size: const Size.square(40),
|
||||||
|
child: svgWidgetWithName("flowy_logo.svg"),
|
||||||
|
),
|
||||||
const VSpace(30),
|
const VSpace(30),
|
||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
|
@ -12,19 +12,6 @@ class AppTheme {
|
||||||
|
|
||||||
bool isDark;
|
bool isDark;
|
||||||
late Color surface; //
|
late Color surface; //
|
||||||
late Color accent1;
|
|
||||||
late Color accent1Dark;
|
|
||||||
late Color accent1Darker;
|
|
||||||
late Color accent2;
|
|
||||||
late Color accent3;
|
|
||||||
late Color grey;
|
|
||||||
late Color greyStrong;
|
|
||||||
late Color greyWeak;
|
|
||||||
late Color error;
|
|
||||||
late Color focus;
|
|
||||||
late Color txt;
|
|
||||||
late Color accentTxt;
|
|
||||||
|
|
||||||
late Color hover;
|
late Color hover;
|
||||||
late Color selector;
|
late Color selector;
|
||||||
late Color red;
|
late Color red;
|
||||||
|
@ -58,10 +45,7 @@ class AppTheme {
|
||||||
late Color main2;
|
late Color main2;
|
||||||
|
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
AppTheme({this.isDark = true}) {
|
AppTheme({this.isDark = true});
|
||||||
txt = isDark ? Colors.white : Colors.black;
|
|
||||||
accentTxt = isDark ? Colors.black : Colors.white;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// fromType factory constructor
|
/// fromType factory constructor
|
||||||
factory AppTheme.fromType(ThemeType t) {
|
factory AppTheme.fromType(ThemeType t) {
|
||||||
|
@ -69,16 +53,6 @@ class AppTheme {
|
||||||
case ThemeType.light:
|
case ThemeType.light:
|
||||||
return AppTheme(isDark: false)
|
return AppTheme(isDark: false)
|
||||||
..surface = Colors.white
|
..surface = Colors.white
|
||||||
..accent1 = const Color(0xff00a086)
|
|
||||||
..accent1Dark = const Color(0xff00856f)
|
|
||||||
..accent1Darker = const Color(0xff006b5a)
|
|
||||||
..accent2 = const Color(0xfff09433)
|
|
||||||
..accent3 = const Color(0xff5bc91a)
|
|
||||||
..greyWeak = const Color(0xff909f9c)
|
|
||||||
..grey = const Color(0xff515d5a)
|
|
||||||
..greyStrong = const Color(0xff151918)
|
|
||||||
..error = Colors.red.shade900
|
|
||||||
..focus = const Color(0xFFe0f8ff)
|
|
||||||
..hover = const Color(0xFFe0f8ff) //
|
..hover = const Color(0xFFe0f8ff) //
|
||||||
..selector = const Color(0xfff2fcff)
|
..selector = const Color(0xfff2fcff)
|
||||||
..red = const Color(0xfffb006d)
|
..red = const Color(0xfffb006d)
|
||||||
|
@ -109,19 +83,7 @@ class AppTheme {
|
||||||
|
|
||||||
case ThemeType.dark:
|
case ThemeType.dark:
|
||||||
return AppTheme(isDark: true)
|
return AppTheme(isDark: true)
|
||||||
..bg1 = const Color(0xff121212)
|
|
||||||
..bg2 = const Color(0xff2c2c2c)
|
|
||||||
..surface = const Color(0xff252525)
|
..surface = const Color(0xff252525)
|
||||||
..accent1 = const Color(0xff00a086)
|
|
||||||
..accent1Dark = const Color(0xff00caa5)
|
|
||||||
..accent1Darker = const Color(0xff00caa5)
|
|
||||||
..accent2 = const Color(0xfff19e46)
|
|
||||||
..accent3 = const Color(0xff5BC91A)
|
|
||||||
..greyWeak = const Color(0xffa8b3b0)
|
|
||||||
..grey = const Color(0xffced4d3)
|
|
||||||
..greyStrong = const Color(0xffffffff)
|
|
||||||
..error = const Color(0xffe55642)
|
|
||||||
..focus = const Color(0xff0ee2b1)
|
|
||||||
..hover = const Color(0xFFe0f8ff) //
|
..hover = const Color(0xFFe0f8ff) //
|
||||||
..selector = const Color(0xfff2fcff)
|
..selector = const Color(0xfff2fcff)
|
||||||
..red = const Color(0xfffb006d)
|
..red = const Color(0xfffb006d)
|
||||||
|
@ -153,8 +115,9 @@ class AppTheme {
|
||||||
}
|
}
|
||||||
|
|
||||||
ThemeData get themeData {
|
ThemeData get themeData {
|
||||||
var t = ThemeData.from(
|
var t = ThemeData(
|
||||||
textTheme: (isDark ? ThemeData.dark() : ThemeData.light()).textTheme,
|
textTheme: (isDark ? ThemeData.dark() : ThemeData.light()).textTheme,
|
||||||
|
textSelectionTheme: TextSelectionThemeData(cursorColor: main1),
|
||||||
colorScheme: ColorScheme(
|
colorScheme: ColorScheme(
|
||||||
brightness: isDark ? Brightness.dark : Brightness.light,
|
brightness: isDark ? Brightness.dark : Brightness.light,
|
||||||
primary: main1,
|
primary: main1,
|
||||||
|
@ -164,15 +127,17 @@ class AppTheme {
|
||||||
background: bg1,
|
background: bg1,
|
||||||
surface: surface,
|
surface: surface,
|
||||||
onBackground: bg1,
|
onBackground: bg1,
|
||||||
onSurface: txt,
|
onSurface: surface,
|
||||||
onError: red,
|
onError: red,
|
||||||
onPrimary: bg1,
|
onPrimary: bg1,
|
||||||
onSecondary: bg1,
|
onSecondary: bg1,
|
||||||
error: error),
|
error: red),
|
||||||
);
|
);
|
||||||
|
|
||||||
return t.copyWith(
|
return t.copyWith(
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
highlightColor: main1,
|
highlightColor: main1,
|
||||||
|
indicatorColor: main1,
|
||||||
toggleableActiveColor: main1);
|
toggleableActiveColor: main1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||||
import 'package:flowy_infra_ui/widget/text_field_container.dart';
|
import 'package:flowy_infra_ui/widget/text_field_container.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flowy_infra/time/duration.dart';
|
import 'package:flowy_infra/time/duration.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class RoundedInputField extends StatefulWidget {
|
class RoundedInputField extends StatefulWidget {
|
||||||
|
@ -10,11 +12,14 @@ class RoundedInputField extends StatefulWidget {
|
||||||
final bool obscureText;
|
final bool obscureText;
|
||||||
final Widget? obscureIcon;
|
final Widget? obscureIcon;
|
||||||
final Widget? obscureHideIcon;
|
final Widget? obscureHideIcon;
|
||||||
|
final FontWeight? fontWeight;
|
||||||
|
final double? fontSize;
|
||||||
final Color normalBorderColor;
|
final Color normalBorderColor;
|
||||||
final Color highlightBorderColor;
|
final Color highlightBorderColor;
|
||||||
final String errorText;
|
final String errorText;
|
||||||
final ValueChanged<String>? onChanged;
|
final ValueChanged<String>? onChanged;
|
||||||
late bool enableObscure;
|
late bool enableObscure;
|
||||||
|
var _text = "";
|
||||||
|
|
||||||
RoundedInputField({
|
RoundedInputField({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
@ -26,6 +31,8 @@ class RoundedInputField extends StatefulWidget {
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
this.normalBorderColor = Colors.transparent,
|
this.normalBorderColor = Colors.transparent,
|
||||||
this.highlightBorderColor = Colors.transparent,
|
this.highlightBorderColor = Colors.transparent,
|
||||||
|
this.fontWeight = FontWeight.normal,
|
||||||
|
this.fontSize = 20,
|
||||||
this.errorText = "",
|
this.errorText = "",
|
||||||
}) : super(key: key) {
|
}) : super(key: key) {
|
||||||
enableObscure = obscureText;
|
enableObscure = obscureText;
|
||||||
|
@ -38,6 +45,7 @@ class RoundedInputField extends StatefulWidget {
|
||||||
class _RoundedInputFieldState extends State<RoundedInputField> {
|
class _RoundedInputFieldState extends State<RoundedInputField> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
final Icon? newIcon = widget.icon == null
|
final Icon? newIcon = widget.icon == null
|
||||||
? null
|
? null
|
||||||
: Icon(
|
: Icon(
|
||||||
|
@ -52,15 +60,23 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
||||||
|
|
||||||
List<Widget> children = [
|
List<Widget> children = [
|
||||||
TextFieldContainer(
|
TextFieldContainer(
|
||||||
|
height: 48,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
borderColor: borderColor,
|
borderColor: borderColor,
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
onChanged: widget.onChanged,
|
onChanged: (value) {
|
||||||
cursorColor: const Color(0xFF6F35A5),
|
widget._text = value;
|
||||||
|
if (widget.onChanged != null) {
|
||||||
|
widget.onChanged!(value);
|
||||||
|
}
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
cursorColor: theme.main1,
|
||||||
obscureText: widget.enableObscure,
|
obscureText: widget.enableObscure,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
icon: newIcon,
|
icon: newIcon,
|
||||||
hintText: widget.hintText,
|
hintText: widget.hintText,
|
||||||
|
hintStyle: TextStyle(color: widget.normalBorderColor),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
suffixIcon: suffixIcon(),
|
suffixIcon: suffixIcon(),
|
||||||
),
|
),
|
||||||
|
@ -71,7 +87,10 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
||||||
if (widget.errorText.isNotEmpty) {
|
if (widget.errorText.isNotEmpty) {
|
||||||
children.add(Text(
|
children.add(Text(
|
||||||
widget.errorText,
|
widget.errorText,
|
||||||
style: TextStyle(color: widget.highlightBorderColor),
|
style: TextStyle(
|
||||||
|
color: widget.highlightBorderColor,
|
||||||
|
fontWeight: widget.fontWeight,
|
||||||
|
fontSize: widget.fontSize),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +108,10 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (widget._text.isEmpty) {
|
||||||
|
return SizedBox.fromSize(size: const Size.square(16));
|
||||||
|
}
|
||||||
|
|
||||||
Widget? icon;
|
Widget? icon;
|
||||||
if (widget.obscureText == true) {
|
if (widget.obscureText == true) {
|
||||||
assert(widget.obscureIcon != null && widget.obscureHideIcon != null);
|
assert(widget.obscureIcon != null && widget.obscureHideIcon != null);
|
||||||
|
@ -104,7 +127,7 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return RoundedImageButton(
|
return RoundedImageButton(
|
||||||
size: 20,
|
size: 16,
|
||||||
press: () {
|
press: () {
|
||||||
widget.enableObscure = !widget.enableObscure;
|
widget.enableObscure = !widget.enableObscure;
|
||||||
setState(() {});
|
setState(() {});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue