add splash screen and config sign up

This commit is contained in:
appflowy 2021-09-06 16:18:34 +08:00
parent 46d1d110e1
commit 024ab85864
34 changed files with 742 additions and 602 deletions

View File

@ -1,11 +1,11 @@
import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/welcome/presentation/welcome_screen.dart'; import 'package:app_flowy/welcome/presentation/splash_screen.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class FlowyAppFactory implements AppFactory { class FlowyAppFactory implements AppFactory {
@override @override
Widget create() { Widget create() {
return const WelcomeScreen(); return const SplashScreen();
} }
} }

View File

@ -42,7 +42,8 @@ class ApplicationBlocObserver extends BlocObserver {
@override @override
// ignore: unnecessary_overrides // ignore: unnecessary_overrides
void onTransition(Bloc bloc, Transition transition) { void onTransition(Bloc bloc, Transition transition) {
Log.debug(transition); Log.debug(
"[current]: ${transition.currentState} \n[next]: ${transition.nextState}");
super.onTransition(bloc, transition); super.onTransition(bloc, transition);
} }

View File

@ -14,28 +14,65 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
Stream<SignUpState> mapEventToState( Stream<SignUpState> mapEventToState(
SignUpEvent event, SignUpEvent event,
) async* { ) async* {
yield* event.map( yield* event.map(signUpWithUserEmailAndPassword: (e) async* {
signUpWithUserEmailAndPassword: (e) async* { yield* _performActionOnSignUp();
yield* _performActionOnSignUp( }, emailChanged: (EmailChanged value) async* {
state, yield state.copyWith(email: value.email, successOrFail: none());
); }, passwordChanged: (PasswordChanged value) async* {
}, yield state.copyWith(password: value.password, successOrFail: none());
emailChanged: (EmailChanged value) async* { }, repeatPasswordChanged: (RepeatPasswordChanged value) async* {
yield state.copyWith(email: value.email, successOrFail: none()); yield state.copyWith(
}, repeatedPassword: value.password, successOrFail: none());
passwordChanged: (PasswordChanged value) async* { });
yield state.copyWith(password: value.password, successOrFail: none());
},
);
} }
Stream<SignUpState> _performActionOnSignUp(SignUpState state) async* { Stream<SignUpState> _performActionOnSignUp() async* {
yield state.copyWith(isSubmitting: true); yield state.copyWith(
isSubmitting: true,
);
final result = await authImpl.signIn(state.email, state.password); final password = state.password;
final repeatedPassword = state.repeatedPassword;
if (password == null) {
yield state.copyWith(
isSubmitting: false,
passwordError: some("Password can't be empty"),
);
return;
}
if (repeatedPassword == null) {
yield state.copyWith(
isSubmitting: false,
repeatPasswordError: some("Repeat password can't be empty"),
);
return;
}
if (password != repeatedPassword) {
yield state.copyWith(
isSubmitting: false,
repeatPasswordError:
some("Repeat password is not the same as password"),
);
return;
}
yield state.copyWith(
passwordError: none(),
repeatPasswordError: none(),
);
final result =
await authImpl.signUp(state.email, state.password, state.email);
yield result.fold( yield result.fold(
(userProfile) => state.copyWith( (userProfile) => state.copyWith(
isSubmitting: false, successOrFail: some(left(userProfile))), isSubmitting: false,
successOrFail: some(left(userProfile)),
emailError: none(),
passwordError: none(),
repeatPasswordError: none(),
),
(error) => stateFromCode(error), (error) => stateFromCode(error),
); );
} }
@ -65,6 +102,8 @@ abstract class SignUpEvent with _$SignUpEvent {
SignUpWithUserEmailAndPassword; SignUpWithUserEmailAndPassword;
const factory SignUpEvent.emailChanged(String email) = EmailChanged; const factory SignUpEvent.emailChanged(String email) = EmailChanged;
const factory SignUpEvent.passwordChanged(String password) = PasswordChanged; const factory SignUpEvent.passwordChanged(String password) = PasswordChanged;
const factory SignUpEvent.repeatPasswordChanged(String password) =
RepeatPasswordChanged;
} }
@freezed @freezed
@ -72,8 +111,10 @@ abstract class SignUpState with _$SignUpState {
const factory SignUpState({ const factory SignUpState({
String? email, String? email,
String? password, String? password,
String? repeatedPassword,
required bool isSubmitting, required bool isSubmitting,
required Option<String> passwordError, required Option<String> passwordError,
required Option<String> repeatPasswordError,
required Option<String> emailError, required Option<String> emailError,
required Option<Either<UserProfile, UserError>> successOrFail, required Option<Either<UserProfile, UserError>> successOrFail,
}) = _SignUpState; }) = _SignUpState;
@ -81,6 +122,7 @@ abstract class SignUpState with _$SignUpState {
factory SignUpState.initial() => SignUpState( factory SignUpState.initial() => SignUpState(
isSubmitting: false, isSubmitting: false,
passwordError: none(), passwordError: none(),
repeatPasswordError: none(),
emailError: none(), emailError: none(),
successOrFail: none(), successOrFail: none(),
); );

View File

@ -31,6 +31,12 @@ class _$SignUpEventTearOff {
password, password,
); );
} }
RepeatPasswordChanged repeatPasswordChanged(String password) {
return RepeatPasswordChanged(
password,
);
}
} }
/// @nodoc /// @nodoc
@ -43,6 +49,7 @@ mixin _$SignUpEvent {
required TResult Function() signUpWithUserEmailAndPassword, required TResult Function() signUpWithUserEmailAndPassword,
required TResult Function(String email) emailChanged, required TResult Function(String email) emailChanged,
required TResult Function(String password) passwordChanged, required TResult Function(String password) passwordChanged,
required TResult Function(String password) repeatPasswordChanged,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
@ -50,6 +57,7 @@ mixin _$SignUpEvent {
TResult Function()? signUpWithUserEmailAndPassword, TResult Function()? signUpWithUserEmailAndPassword,
TResult Function(String email)? emailChanged, TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged, TResult Function(String password)? passwordChanged,
TResult Function(String password)? repeatPasswordChanged,
required TResult orElse(), required TResult orElse(),
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@ -59,6 +67,8 @@ mixin _$SignUpEvent {
signUpWithUserEmailAndPassword, signUpWithUserEmailAndPassword,
required TResult Function(EmailChanged value) emailChanged, required TResult Function(EmailChanged value) emailChanged,
required TResult Function(PasswordChanged value) passwordChanged, required TResult Function(PasswordChanged value) passwordChanged,
required TResult Function(RepeatPasswordChanged value)
repeatPasswordChanged,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
@ -67,6 +77,7 @@ mixin _$SignUpEvent {
signUpWithUserEmailAndPassword, signUpWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged, TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged, TResult Function(PasswordChanged value)? passwordChanged,
TResult Function(RepeatPasswordChanged value)? repeatPasswordChanged,
required TResult orElse(), required TResult orElse(),
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@ -135,6 +146,7 @@ class _$SignUpWithUserEmailAndPassword
required TResult Function() signUpWithUserEmailAndPassword, required TResult Function() signUpWithUserEmailAndPassword,
required TResult Function(String email) emailChanged, required TResult Function(String email) emailChanged,
required TResult Function(String password) passwordChanged, required TResult Function(String password) passwordChanged,
required TResult Function(String password) repeatPasswordChanged,
}) { }) {
return signUpWithUserEmailAndPassword(); return signUpWithUserEmailAndPassword();
} }
@ -145,6 +157,7 @@ class _$SignUpWithUserEmailAndPassword
TResult Function()? signUpWithUserEmailAndPassword, TResult Function()? signUpWithUserEmailAndPassword,
TResult Function(String email)? emailChanged, TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged, TResult Function(String password)? passwordChanged,
TResult Function(String password)? repeatPasswordChanged,
required TResult orElse(), required TResult orElse(),
}) { }) {
if (signUpWithUserEmailAndPassword != null) { if (signUpWithUserEmailAndPassword != null) {
@ -160,6 +173,8 @@ class _$SignUpWithUserEmailAndPassword
signUpWithUserEmailAndPassword, signUpWithUserEmailAndPassword,
required TResult Function(EmailChanged value) emailChanged, required TResult Function(EmailChanged value) emailChanged,
required TResult Function(PasswordChanged value) passwordChanged, required TResult Function(PasswordChanged value) passwordChanged,
required TResult Function(RepeatPasswordChanged value)
repeatPasswordChanged,
}) { }) {
return signUpWithUserEmailAndPassword(this); return signUpWithUserEmailAndPassword(this);
} }
@ -171,6 +186,7 @@ class _$SignUpWithUserEmailAndPassword
signUpWithUserEmailAndPassword, signUpWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged, TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged, TResult Function(PasswordChanged value)? passwordChanged,
TResult Function(RepeatPasswordChanged value)? repeatPasswordChanged,
required TResult orElse(), required TResult orElse(),
}) { }) {
if (signUpWithUserEmailAndPassword != null) { if (signUpWithUserEmailAndPassword != null) {
@ -252,6 +268,7 @@ class _$EmailChanged implements EmailChanged {
required TResult Function() signUpWithUserEmailAndPassword, required TResult Function() signUpWithUserEmailAndPassword,
required TResult Function(String email) emailChanged, required TResult Function(String email) emailChanged,
required TResult Function(String password) passwordChanged, required TResult Function(String password) passwordChanged,
required TResult Function(String password) repeatPasswordChanged,
}) { }) {
return emailChanged(email); return emailChanged(email);
} }
@ -262,6 +279,7 @@ class _$EmailChanged implements EmailChanged {
TResult Function()? signUpWithUserEmailAndPassword, TResult Function()? signUpWithUserEmailAndPassword,
TResult Function(String email)? emailChanged, TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged, TResult Function(String password)? passwordChanged,
TResult Function(String password)? repeatPasswordChanged,
required TResult orElse(), required TResult orElse(),
}) { }) {
if (emailChanged != null) { if (emailChanged != null) {
@ -277,6 +295,8 @@ class _$EmailChanged implements EmailChanged {
signUpWithUserEmailAndPassword, signUpWithUserEmailAndPassword,
required TResult Function(EmailChanged value) emailChanged, required TResult Function(EmailChanged value) emailChanged,
required TResult Function(PasswordChanged value) passwordChanged, required TResult Function(PasswordChanged value) passwordChanged,
required TResult Function(RepeatPasswordChanged value)
repeatPasswordChanged,
}) { }) {
return emailChanged(this); return emailChanged(this);
} }
@ -288,6 +308,7 @@ class _$EmailChanged implements EmailChanged {
signUpWithUserEmailAndPassword, signUpWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged, TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged, TResult Function(PasswordChanged value)? passwordChanged,
TResult Function(RepeatPasswordChanged value)? repeatPasswordChanged,
required TResult orElse(), required TResult orElse(),
}) { }) {
if (emailChanged != null) { if (emailChanged != null) {
@ -375,6 +396,7 @@ class _$PasswordChanged implements PasswordChanged {
required TResult Function() signUpWithUserEmailAndPassword, required TResult Function() signUpWithUserEmailAndPassword,
required TResult Function(String email) emailChanged, required TResult Function(String email) emailChanged,
required TResult Function(String password) passwordChanged, required TResult Function(String password) passwordChanged,
required TResult Function(String password) repeatPasswordChanged,
}) { }) {
return passwordChanged(password); return passwordChanged(password);
} }
@ -385,6 +407,7 @@ class _$PasswordChanged implements PasswordChanged {
TResult Function()? signUpWithUserEmailAndPassword, TResult Function()? signUpWithUserEmailAndPassword,
TResult Function(String email)? emailChanged, TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged, TResult Function(String password)? passwordChanged,
TResult Function(String password)? repeatPasswordChanged,
required TResult orElse(), required TResult orElse(),
}) { }) {
if (passwordChanged != null) { if (passwordChanged != null) {
@ -400,6 +423,8 @@ class _$PasswordChanged implements PasswordChanged {
signUpWithUserEmailAndPassword, signUpWithUserEmailAndPassword,
required TResult Function(EmailChanged value) emailChanged, required TResult Function(EmailChanged value) emailChanged,
required TResult Function(PasswordChanged value) passwordChanged, required TResult Function(PasswordChanged value) passwordChanged,
required TResult Function(RepeatPasswordChanged value)
repeatPasswordChanged,
}) { }) {
return passwordChanged(this); return passwordChanged(this);
} }
@ -411,6 +436,7 @@ class _$PasswordChanged implements PasswordChanged {
signUpWithUserEmailAndPassword, signUpWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged, TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged, TResult Function(PasswordChanged value)? passwordChanged,
TResult Function(RepeatPasswordChanged value)? repeatPasswordChanged,
required TResult orElse(), required TResult orElse(),
}) { }) {
if (passwordChanged != null) { if (passwordChanged != null) {
@ -429,6 +455,136 @@ abstract class PasswordChanged implements SignUpEvent {
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
} }
/// @nodoc
abstract class $RepeatPasswordChangedCopyWith<$Res> {
factory $RepeatPasswordChangedCopyWith(RepeatPasswordChanged value,
$Res Function(RepeatPasswordChanged) then) =
_$RepeatPasswordChangedCopyWithImpl<$Res>;
$Res call({String password});
}
/// @nodoc
class _$RepeatPasswordChangedCopyWithImpl<$Res>
extends _$SignUpEventCopyWithImpl<$Res>
implements $RepeatPasswordChangedCopyWith<$Res> {
_$RepeatPasswordChangedCopyWithImpl(
RepeatPasswordChanged _value, $Res Function(RepeatPasswordChanged) _then)
: super(_value, (v) => _then(v as RepeatPasswordChanged));
@override
RepeatPasswordChanged get _value => super._value as RepeatPasswordChanged;
@override
$Res call({
Object? password = freezed,
}) {
return _then(RepeatPasswordChanged(
password == freezed
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$RepeatPasswordChanged implements RepeatPasswordChanged {
const _$RepeatPasswordChanged(this.password);
@override
final String password;
@override
String toString() {
return 'SignUpEvent.repeatPasswordChanged(password: $password)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is RepeatPasswordChanged &&
(identical(other.password, password) ||
const DeepCollectionEquality()
.equals(other.password, password)));
}
@override
int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(password);
@JsonKey(ignore: true)
@override
$RepeatPasswordChangedCopyWith<RepeatPasswordChanged> get copyWith =>
_$RepeatPasswordChangedCopyWithImpl<RepeatPasswordChanged>(
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,
required TResult Function(String password) repeatPasswordChanged,
}) {
return repeatPasswordChanged(password);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? signUpWithUserEmailAndPassword,
TResult Function(String email)? emailChanged,
TResult Function(String password)? passwordChanged,
TResult Function(String password)? repeatPasswordChanged,
required TResult orElse(),
}) {
if (repeatPasswordChanged != null) {
return repeatPasswordChanged(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,
required TResult Function(RepeatPasswordChanged value)
repeatPasswordChanged,
}) {
return repeatPasswordChanged(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(SignUpWithUserEmailAndPassword value)?
signUpWithUserEmailAndPassword,
TResult Function(EmailChanged value)? emailChanged,
TResult Function(PasswordChanged value)? passwordChanged,
TResult Function(RepeatPasswordChanged value)? repeatPasswordChanged,
required TResult orElse(),
}) {
if (repeatPasswordChanged != null) {
return repeatPasswordChanged(this);
}
return orElse();
}
}
abstract class RepeatPasswordChanged implements SignUpEvent {
const factory RepeatPasswordChanged(String password) =
_$RepeatPasswordChanged;
String get password => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$RepeatPasswordChangedCopyWith<RepeatPasswordChanged> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc /// @nodoc
class _$SignUpStateTearOff { class _$SignUpStateTearOff {
const _$SignUpStateTearOff(); const _$SignUpStateTearOff();
@ -436,15 +592,19 @@ class _$SignUpStateTearOff {
_SignUpState call( _SignUpState call(
{String? email, {String? email,
String? password, String? password,
String? repeatedPassword,
required bool isSubmitting, required bool isSubmitting,
required Option<String> passwordError, required Option<String> passwordError,
required Option<String> repeatPasswordError,
required Option<String> emailError, required Option<String> emailError,
required Option<Either<UserProfile, UserError>> successOrFail}) { required Option<Either<UserProfile, UserError>> successOrFail}) {
return _SignUpState( return _SignUpState(
email: email, email: email,
password: password, password: password,
repeatedPassword: repeatedPassword,
isSubmitting: isSubmitting, isSubmitting: isSubmitting,
passwordError: passwordError, passwordError: passwordError,
repeatPasswordError: repeatPasswordError,
emailError: emailError, emailError: emailError,
successOrFail: successOrFail, successOrFail: successOrFail,
); );
@ -458,8 +618,10 @@ const $SignUpState = _$SignUpStateTearOff();
mixin _$SignUpState { mixin _$SignUpState {
String? get email => throw _privateConstructorUsedError; String? get email => throw _privateConstructorUsedError;
String? get password => throw _privateConstructorUsedError; String? get password => throw _privateConstructorUsedError;
String? get repeatedPassword => throw _privateConstructorUsedError;
bool get isSubmitting => throw _privateConstructorUsedError; bool get isSubmitting => throw _privateConstructorUsedError;
Option<String> get passwordError => throw _privateConstructorUsedError; Option<String> get passwordError => throw _privateConstructorUsedError;
Option<String> get repeatPasswordError => throw _privateConstructorUsedError;
Option<String> get emailError => throw _privateConstructorUsedError; Option<String> get emailError => throw _privateConstructorUsedError;
Option<Either<UserProfile, UserError>> get successOrFail => Option<Either<UserProfile, UserError>> get successOrFail =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@ -477,8 +639,10 @@ abstract class $SignUpStateCopyWith<$Res> {
$Res call( $Res call(
{String? email, {String? email,
String? password, String? password,
String? repeatedPassword,
bool isSubmitting, bool isSubmitting,
Option<String> passwordError, Option<String> passwordError,
Option<String> repeatPasswordError,
Option<String> emailError, Option<String> emailError,
Option<Either<UserProfile, UserError>> successOrFail}); Option<Either<UserProfile, UserError>> successOrFail});
} }
@ -495,8 +659,10 @@ class _$SignUpStateCopyWithImpl<$Res> implements $SignUpStateCopyWith<$Res> {
$Res call({ $Res call({
Object? email = freezed, Object? email = freezed,
Object? password = freezed, Object? password = freezed,
Object? repeatedPassword = freezed,
Object? isSubmitting = freezed, Object? isSubmitting = freezed,
Object? passwordError = freezed, Object? passwordError = freezed,
Object? repeatPasswordError = freezed,
Object? emailError = freezed, Object? emailError = freezed,
Object? successOrFail = freezed, Object? successOrFail = freezed,
}) { }) {
@ -509,6 +675,10 @@ class _$SignUpStateCopyWithImpl<$Res> implements $SignUpStateCopyWith<$Res> {
? _value.password ? _value.password
: password // ignore: cast_nullable_to_non_nullable : password // ignore: cast_nullable_to_non_nullable
as String?, as String?,
repeatedPassword: repeatedPassword == freezed
? _value.repeatedPassword
: repeatedPassword // ignore: cast_nullable_to_non_nullable
as String?,
isSubmitting: isSubmitting == freezed isSubmitting: isSubmitting == freezed
? _value.isSubmitting ? _value.isSubmitting
: isSubmitting // ignore: cast_nullable_to_non_nullable : isSubmitting // ignore: cast_nullable_to_non_nullable
@ -517,6 +687,10 @@ class _$SignUpStateCopyWithImpl<$Res> implements $SignUpStateCopyWith<$Res> {
? _value.passwordError ? _value.passwordError
: passwordError // ignore: cast_nullable_to_non_nullable : passwordError // ignore: cast_nullable_to_non_nullable
as Option<String>, as Option<String>,
repeatPasswordError: repeatPasswordError == freezed
? _value.repeatPasswordError
: repeatPasswordError // ignore: cast_nullable_to_non_nullable
as Option<String>,
emailError: emailError == freezed emailError: emailError == freezed
? _value.emailError ? _value.emailError
: emailError // ignore: cast_nullable_to_non_nullable : emailError // ignore: cast_nullable_to_non_nullable
@ -539,8 +713,10 @@ abstract class _$SignUpStateCopyWith<$Res>
$Res call( $Res call(
{String? email, {String? email,
String? password, String? password,
String? repeatedPassword,
bool isSubmitting, bool isSubmitting,
Option<String> passwordError, Option<String> passwordError,
Option<String> repeatPasswordError,
Option<String> emailError, Option<String> emailError,
Option<Either<UserProfile, UserError>> successOrFail}); Option<Either<UserProfile, UserError>> successOrFail});
} }
@ -559,8 +735,10 @@ class __$SignUpStateCopyWithImpl<$Res> extends _$SignUpStateCopyWithImpl<$Res>
$Res call({ $Res call({
Object? email = freezed, Object? email = freezed,
Object? password = freezed, Object? password = freezed,
Object? repeatedPassword = freezed,
Object? isSubmitting = freezed, Object? isSubmitting = freezed,
Object? passwordError = freezed, Object? passwordError = freezed,
Object? repeatPasswordError = freezed,
Object? emailError = freezed, Object? emailError = freezed,
Object? successOrFail = freezed, Object? successOrFail = freezed,
}) { }) {
@ -573,6 +751,10 @@ class __$SignUpStateCopyWithImpl<$Res> extends _$SignUpStateCopyWithImpl<$Res>
? _value.password ? _value.password
: password // ignore: cast_nullable_to_non_nullable : password // ignore: cast_nullable_to_non_nullable
as String?, as String?,
repeatedPassword: repeatedPassword == freezed
? _value.repeatedPassword
: repeatedPassword // ignore: cast_nullable_to_non_nullable
as String?,
isSubmitting: isSubmitting == freezed isSubmitting: isSubmitting == freezed
? _value.isSubmitting ? _value.isSubmitting
: isSubmitting // ignore: cast_nullable_to_non_nullable : isSubmitting // ignore: cast_nullable_to_non_nullable
@ -581,6 +763,10 @@ class __$SignUpStateCopyWithImpl<$Res> extends _$SignUpStateCopyWithImpl<$Res>
? _value.passwordError ? _value.passwordError
: passwordError // ignore: cast_nullable_to_non_nullable : passwordError // ignore: cast_nullable_to_non_nullable
as Option<String>, as Option<String>,
repeatPasswordError: repeatPasswordError == freezed
? _value.repeatPasswordError
: repeatPasswordError // ignore: cast_nullable_to_non_nullable
as Option<String>,
emailError: emailError == freezed emailError: emailError == freezed
? _value.emailError ? _value.emailError
: emailError // ignore: cast_nullable_to_non_nullable : emailError // ignore: cast_nullable_to_non_nullable
@ -599,8 +785,10 @@ class _$_SignUpState implements _SignUpState {
const _$_SignUpState( const _$_SignUpState(
{this.email, {this.email,
this.password, this.password,
this.repeatedPassword,
required this.isSubmitting, required this.isSubmitting,
required this.passwordError, required this.passwordError,
required this.repeatPasswordError,
required this.emailError, required this.emailError,
required this.successOrFail}); required this.successOrFail});
@ -609,17 +797,21 @@ class _$_SignUpState implements _SignUpState {
@override @override
final String? password; final String? password;
@override @override
final String? repeatedPassword;
@override
final bool isSubmitting; final bool isSubmitting;
@override @override
final Option<String> passwordError; final Option<String> passwordError;
@override @override
final Option<String> repeatPasswordError;
@override
final Option<String> emailError; final Option<String> emailError;
@override @override
final Option<Either<UserProfile, UserError>> successOrFail; final Option<Either<UserProfile, UserError>> successOrFail;
@override @override
String toString() { String toString() {
return 'SignUpState(email: $email, password: $password, isSubmitting: $isSubmitting, passwordError: $passwordError, emailError: $emailError, successOrFail: $successOrFail)'; return 'SignUpState(email: $email, password: $password, repeatedPassword: $repeatedPassword, isSubmitting: $isSubmitting, passwordError: $passwordError, repeatPasswordError: $repeatPasswordError, emailError: $emailError, successOrFail: $successOrFail)';
} }
@override @override
@ -631,12 +823,18 @@ class _$_SignUpState implements _SignUpState {
(identical(other.password, password) || (identical(other.password, password) ||
const DeepCollectionEquality() const DeepCollectionEquality()
.equals(other.password, password)) && .equals(other.password, password)) &&
(identical(other.repeatedPassword, repeatedPassword) ||
const DeepCollectionEquality()
.equals(other.repeatedPassword, repeatedPassword)) &&
(identical(other.isSubmitting, isSubmitting) || (identical(other.isSubmitting, isSubmitting) ||
const DeepCollectionEquality() const DeepCollectionEquality()
.equals(other.isSubmitting, isSubmitting)) && .equals(other.isSubmitting, isSubmitting)) &&
(identical(other.passwordError, passwordError) || (identical(other.passwordError, passwordError) ||
const DeepCollectionEquality() const DeepCollectionEquality()
.equals(other.passwordError, passwordError)) && .equals(other.passwordError, passwordError)) &&
(identical(other.repeatPasswordError, repeatPasswordError) ||
const DeepCollectionEquality()
.equals(other.repeatPasswordError, repeatPasswordError)) &&
(identical(other.emailError, emailError) || (identical(other.emailError, emailError) ||
const DeepCollectionEquality() const DeepCollectionEquality()
.equals(other.emailError, emailError)) && .equals(other.emailError, emailError)) &&
@ -650,8 +848,10 @@ class _$_SignUpState implements _SignUpState {
runtimeType.hashCode ^ runtimeType.hashCode ^
const DeepCollectionEquality().hash(email) ^ const DeepCollectionEquality().hash(email) ^
const DeepCollectionEquality().hash(password) ^ const DeepCollectionEquality().hash(password) ^
const DeepCollectionEquality().hash(repeatedPassword) ^
const DeepCollectionEquality().hash(isSubmitting) ^ const DeepCollectionEquality().hash(isSubmitting) ^
const DeepCollectionEquality().hash(passwordError) ^ const DeepCollectionEquality().hash(passwordError) ^
const DeepCollectionEquality().hash(repeatPasswordError) ^
const DeepCollectionEquality().hash(emailError) ^ const DeepCollectionEquality().hash(emailError) ^
const DeepCollectionEquality().hash(successOrFail); const DeepCollectionEquality().hash(successOrFail);
@ -665,8 +865,10 @@ abstract class _SignUpState implements SignUpState {
const factory _SignUpState( const factory _SignUpState(
{String? email, {String? email,
String? password, String? password,
String? repeatedPassword,
required bool isSubmitting, required bool isSubmitting,
required Option<String> passwordError, required Option<String> passwordError,
required Option<String> repeatPasswordError,
required Option<String> emailError, required Option<String> emailError,
required Option<Either<UserProfile, UserError>> successOrFail}) = required Option<Either<UserProfile, UserError>> successOrFail}) =
_$_SignUpState; _$_SignUpState;
@ -676,10 +878,14 @@ abstract class _SignUpState implements SignUpState {
@override @override
String? get password => throw _privateConstructorUsedError; String? get password => throw _privateConstructorUsedError;
@override @override
String? get repeatedPassword => throw _privateConstructorUsedError;
@override
bool get isSubmitting => throw _privateConstructorUsedError; bool get isSubmitting => throw _privateConstructorUsedError;
@override @override
Option<String> get passwordError => throw _privateConstructorUsedError; Option<String> get passwordError => throw _privateConstructorUsedError;
@override @override
Option<String> get repeatPasswordError => throw _privateConstructorUsedError;
@override
Option<String> get emailError => throw _privateConstructorUsedError; Option<String> get emailError => throw _privateConstructorUsedError;
@override @override
Option<Either<UserProfile, UserError>> get successOrFail => Option<Either<UserProfile, UserError>> get successOrFail =>

View File

@ -12,7 +12,7 @@ abstract class IAuth {
} }
abstract class IAuthRouter { abstract class IAuthRouter {
void showWorkspaceSelectScreen(BuildContext context, UserProfile user); void pushWelcomeScreen(BuildContext context, UserProfile userProfile);
void showSignUpScreen(BuildContext context); void pushSignUpScreen(BuildContext context);
void showForgetPasswordScreen(BuildContext context); void pushForgetPasswordScreen(BuildContext context);
} }

View File

@ -1,4 +1,6 @@
import 'package:app_flowy/user/presentation/sign_up/sign_up_screen.dart'; import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/user/presentation/sign_up_screen.dart';
import 'package:app_flowy/welcome/domain/i_welcome.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';
@ -34,26 +36,20 @@ class AuthImpl extends IAuth {
class AuthRouterImpl extends IAuthRouter { class AuthRouterImpl extends IAuthRouter {
@override @override
void showForgetPasswordScreen(BuildContext context) { void pushForgetPasswordScreen(BuildContext context) {
// TODO: implement showForgetPasswordScreen // TODO: implement showForgetPasswordScreen
} }
@override @override
void showWorkspaceSelectScreen(BuildContext context, UserProfile user) { void pushWelcomeScreen(BuildContext context, UserProfile userProfile) {
Navigator.of(context).push( getIt<IWelcomeRoute>().pushWelcomeScreen(context, userProfile);
PageRoutes.fade(
() => WorkspaceSelectScreen(
repo: UserRepo(user: user),
),
),
);
} }
@override @override
void showSignUpScreen(BuildContext context) { void pushSignUpScreen(BuildContext context) {
Navigator.of(context).push( Navigator.of(context).push(
PageRoutes.fade( PageRoutes.fade(
() => const SignUpScreen(), () => SignUpScreen(router: getIt<IAuthRouter>()),
), ),
); );
} }

View File

@ -1,7 +1,7 @@
import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/user/application/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/widgets/background.dart';
import 'package:flowy_infra/theme.dart'; 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/rounded_input_field.dart'; import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
@ -38,7 +38,7 @@ class SignInScreen extends StatelessWidget {
void _handleSuccessOrFail( void _handleSuccessOrFail(
Either<UserProfile, UserError> result, BuildContext context) { Either<UserProfile, UserError> result, BuildContext context) {
result.fold( result.fold(
(user) => router.showWorkspaceSelectScreen(context, user), (user) => router.pushWelcomeScreen(context, user),
(error) => _showErrorMessage(context, error.msg), (error) => _showErrorMessage(context, error.msg),
); );
} }
@ -106,7 +106,7 @@ class SignUpPrompt extends StatelessWidget {
style: TextButton.styleFrom( style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 12), textStyle: const TextStyle(fontSize: 12),
), ),
onPressed: () => router.showSignUpScreen(context), onPressed: () => router.pushSignUpScreen(context),
child: Text( child: Text(
'Sign Up', 'Sign Up',
style: TextStyle(color: theme.main1), style: TextStyle(color: theme.main1),
@ -155,7 +155,7 @@ class ForgetPasswordButton extends StatelessWidget {
style: TextButton.styleFrom( style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 12), textStyle: const TextStyle(fontSize: 12),
), ),
onPressed: () => router.showForgetPasswordScreen(context), onPressed: () => router.pushForgetPasswordScreen(context),
child: Text( child: Text(
'Forgot Password?', 'Forgot Password?',
style: TextStyle(color: theme.main1), style: TextStyle(color: theme.main1),
@ -178,6 +178,7 @@ class PasswordTextField extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return RoundedInputField( return RoundedInputField(
obscureText: true, obscureText: true,
fontSize: 14,
obscureIcon: svgWidgetWithName("home/Hide.svg"), obscureIcon: svgWidgetWithName("home/Hide.svg"),
obscureHideIcon: svgWidgetWithName("home/Show.svg"), obscureHideIcon: svgWidgetWithName("home/Show.svg"),
hintText: 'Password', hintText: 'Password',
@ -211,6 +212,7 @@ class EmailTextField extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return RoundedInputField( return RoundedInputField(
hintText: 'Email', hintText: 'Email',
fontSize: 14,
normalBorderColor: theme.shader4, normalBorderColor: theme.shader4,
highlightBorderColor: theme.red, highlightBorderColor: theme.red,
errorText: context errorText: context

View File

@ -1,5 +1,6 @@
import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/user/application/sign_up_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/presentation/widgets/background.dart'; import 'package:app_flowy/user/presentation/widgets/background.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart';
@ -13,7 +14,8 @@ import 'package:dartz/dartz.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
class SignUpScreen extends StatelessWidget { class SignUpScreen extends StatelessWidget {
const SignUpScreen({Key? key}) : super(key: key); final IAuthRouter router;
const SignUpScreen({Key? key, required this.router}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -22,31 +24,23 @@ class SignUpScreen extends StatelessWidget {
child: BlocListener<SignUpBloc, SignUpState>( child: BlocListener<SignUpBloc, SignUpState>(
listener: (context, state) { listener: (context, state) {
state.successOrFail.fold( state.successOrFail.fold(
() => null, () => {},
(result) => _handleSuccessOrFail(result, context), (result) => _handleSuccessOrFail(context, result),
); );
}, },
child: const Scaffold( child: const Scaffold(body: SignUpForm()),
body: SignUpForm(),
),
), ),
); );
} }
void _handleSuccessOrFail( void _handleSuccessOrFail(
Either<UserProfile, UserError> result, BuildContext context) { BuildContext context, Either<UserProfile, UserError> result) {
result.fold( result.fold(
(user) => { (user) => router.pushWelcomeScreen(context, user),
// router.showWorkspaceSelectScreen(context, user) (error) => ScaffoldMessenger.of(context).showSnackBar(
}, SnackBar(
(error) => _showErrorMessage(context, error.msg), content: Text(error.msg),
); ),
}
void _showErrorMessage(BuildContext context, String msg) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(msg),
), ),
); );
} }
@ -70,7 +64,7 @@ class SignUpForm extends StatelessWidget {
const VSpace(30), const VSpace(30),
const EmailTextField(), const EmailTextField(),
const PasswordTextField(), const PasswordTextField(),
const PasswordTextField(hintText: "Repeate password"), const RepeatPasswordTextField(),
const VSpace(30), const VSpace(30),
const SignUpButton(), const SignUpButton(),
const VSpace(10), const VSpace(10),
@ -95,17 +89,14 @@ class SignUpPrompt extends StatelessWidget {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return Row( return Row(
children: [ children: [
Text("Already have an account", Text(
style: TextStyle(color: theme.shader3, fontSize: 12)), "Already have an account?",
style: TextStyle(color: theme.shader3, fontSize: 12),
),
TextButton( TextButton(
style: TextButton.styleFrom( style: TextButton.styleFrom(textStyle: const TextStyle(fontSize: 12)),
textStyle: const TextStyle(fontSize: 12),
),
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
child: Text( child: Text('Sign In', style: TextStyle(color: theme.main1)),
'Sign In',
style: TextStyle(color: theme.main1),
),
), ),
], ],
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -136,10 +127,8 @@ class SignUpButton extends StatelessWidget {
} }
class PasswordTextField extends StatelessWidget { class PasswordTextField extends StatelessWidget {
final String hintText;
const PasswordTextField({ const PasswordTextField({
Key? key, Key? key,
this.hintText = "Password",
}) : super(key: key); }) : super(key: key);
@override @override
@ -155,7 +144,7 @@ class PasswordTextField extends StatelessWidget {
obscureHideIcon: svgWidgetWithName("home/Show.svg"), obscureHideIcon: svgWidgetWithName("home/Show.svg"),
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
hintText: hintText, hintText: "Password",
normalBorderColor: theme.shader4, normalBorderColor: theme.shader4,
highlightBorderColor: theme.red, highlightBorderColor: theme.red,
errorText: context errorText: context
@ -172,6 +161,41 @@ class PasswordTextField extends StatelessWidget {
} }
} }
class RepeatPasswordTextField extends StatelessWidget {
const RepeatPasswordTextField({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return BlocBuilder<SignUpBloc, SignUpState>(
buildWhen: (previous, current) =>
previous.repeatPasswordError != current.repeatPasswordError,
builder: (context, state) {
return RoundedInputField(
obscureText: true,
obscureIcon: svgWidgetWithName("home/Hide.svg"),
obscureHideIcon: svgWidgetWithName("home/Show.svg"),
fontSize: 14,
fontWeight: FontWeight.w500,
hintText: "Repeate password",
normalBorderColor: theme.shader4,
highlightBorderColor: theme.red,
errorText: context
.read<SignUpBloc>()
.state
.repeatPasswordError
.fold(() => "", (error) => error),
onChanged: (value) => context
.read<SignUpBloc>()
.add(SignUpEvent.repeatPasswordChanged(value)),
);
},
);
}
}
class EmailTextField extends StatelessWidget { class EmailTextField extends StatelessWidget {
const EmailTextField({ const EmailTextField({
Key? key, Key? key,
@ -186,6 +210,7 @@ class EmailTextField extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return RoundedInputField( return RoundedInputField(
hintText: 'Email', hintText: 'Email',
fontSize: 14,
normalBorderColor: theme.shader4, normalBorderColor: theme.shader4,
highlightBorderColor: theme.red, highlightBorderColor: theme.red,
errorText: context errorText: context

View File

@ -3,14 +3,14 @@ import 'package:app_flowy/welcome/domain/i_welcome.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
part 'welcome_bloc.freezed.dart'; part 'splash_bloc.freezed.dart';
class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> { class SplashBloc extends Bloc<SplashEvent, SplashState> {
final IWelcomeAuth authImpl; final ISplashAuth authImpl;
WelcomeBloc(this.authImpl) : super(WelcomeState.initial()); SplashBloc(this.authImpl) : super(SplashState.initial());
@override @override
Stream<WelcomeState> mapEventToState(WelcomeEvent event) async* { Stream<SplashState> mapEventToState(SplashEvent event) async* {
yield* event.map( yield* event.map(
getUser: (val) async* { getUser: (val) async* {
final authState = await authImpl.currentUserProfile(); final authState = await authImpl.currentUserProfile();
@ -21,17 +21,17 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
} }
@freezed @freezed
abstract class WelcomeEvent with _$WelcomeEvent { abstract class SplashEvent with _$SplashEvent {
const factory WelcomeEvent.getUser() = _GetUser; const factory SplashEvent.getUser() = _GetUser;
} }
@freezed @freezed
abstract class WelcomeState implements _$WelcomeState { abstract class SplashState implements _$SplashState {
const factory WelcomeState({ const factory SplashState({
required AuthState auth, required AuthState auth,
}) = _WelcomeState; }) = _SplashState;
factory WelcomeState.initial() => const WelcomeState( factory SplashState.initial() => const SplashState(
auth: AuthState.initial(), auth: AuthState.initial(),
); );
} }

View File

@ -1,7 +1,7 @@
// GENERATED CODE - DO NOT MODIFY BY HAND // 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 // 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 'welcome_bloc.dart'; part of 'splash_bloc.dart';
// ************************************************************************** // **************************************************************************
// FreezedGenerator // FreezedGenerator
@ -13,8 +13,8 @@ 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'); '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 /// @nodoc
class _$WelcomeEventTearOff { class _$SplashEventTearOff {
const _$WelcomeEventTearOff(); const _$SplashEventTearOff();
_GetUser getUser() { _GetUser getUser() {
return const _GetUser(); return const _GetUser();
@ -22,10 +22,10 @@ class _$WelcomeEventTearOff {
} }
/// @nodoc /// @nodoc
const $WelcomeEvent = _$WelcomeEventTearOff(); const $SplashEvent = _$SplashEventTearOff();
/// @nodoc /// @nodoc
mixin _$WelcomeEvent { mixin _$SplashEvent {
@optionalTypeArgs @optionalTypeArgs
TResult when<TResult extends Object?>({ TResult when<TResult extends Object?>({
required TResult Function() getUser, required TResult Function() getUser,
@ -51,19 +51,19 @@ mixin _$WelcomeEvent {
} }
/// @nodoc /// @nodoc
abstract class $WelcomeEventCopyWith<$Res> { abstract class $SplashEventCopyWith<$Res> {
factory $WelcomeEventCopyWith( factory $SplashEventCopyWith(
WelcomeEvent value, $Res Function(WelcomeEvent) then) = SplashEvent value, $Res Function(SplashEvent) then) =
_$WelcomeEventCopyWithImpl<$Res>; _$SplashEventCopyWithImpl<$Res>;
} }
/// @nodoc /// @nodoc
class _$WelcomeEventCopyWithImpl<$Res> implements $WelcomeEventCopyWith<$Res> { class _$SplashEventCopyWithImpl<$Res> implements $SplashEventCopyWith<$Res> {
_$WelcomeEventCopyWithImpl(this._value, this._then); _$SplashEventCopyWithImpl(this._value, this._then);
final WelcomeEvent _value; final SplashEvent _value;
// ignore: unused_field // ignore: unused_field
final $Res Function(WelcomeEvent) _then; final $Res Function(SplashEvent) _then;
} }
/// @nodoc /// @nodoc
@ -73,7 +73,7 @@ abstract class _$GetUserCopyWith<$Res> {
} }
/// @nodoc /// @nodoc
class __$GetUserCopyWithImpl<$Res> extends _$WelcomeEventCopyWithImpl<$Res> class __$GetUserCopyWithImpl<$Res> extends _$SplashEventCopyWithImpl<$Res>
implements _$GetUserCopyWith<$Res> { implements _$GetUserCopyWith<$Res> {
__$GetUserCopyWithImpl(_GetUser _value, $Res Function(_GetUser) _then) __$GetUserCopyWithImpl(_GetUser _value, $Res Function(_GetUser) _then)
: super(_value, (v) => _then(v as _GetUser)); : super(_value, (v) => _then(v as _GetUser));
@ -89,7 +89,7 @@ class _$_GetUser implements _GetUser {
@override @override
String toString() { String toString() {
return 'WelcomeEvent.getUser()'; return 'SplashEvent.getUser()';
} }
@override @override
@ -141,50 +141,50 @@ class _$_GetUser implements _GetUser {
} }
} }
abstract class _GetUser implements WelcomeEvent { abstract class _GetUser implements SplashEvent {
const factory _GetUser() = _$_GetUser; const factory _GetUser() = _$_GetUser;
} }
/// @nodoc /// @nodoc
class _$WelcomeStateTearOff { class _$SplashStateTearOff {
const _$WelcomeStateTearOff(); const _$SplashStateTearOff();
_WelcomeState call({required AuthState auth}) { _SplashState call({required AuthState auth}) {
return _WelcomeState( return _SplashState(
auth: auth, auth: auth,
); );
} }
} }
/// @nodoc /// @nodoc
const $WelcomeState = _$WelcomeStateTearOff(); const $SplashState = _$SplashStateTearOff();
/// @nodoc /// @nodoc
mixin _$WelcomeState { mixin _$SplashState {
AuthState get auth => throw _privateConstructorUsedError; AuthState get auth => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
$WelcomeStateCopyWith<WelcomeState> get copyWith => $SplashStateCopyWith<SplashState> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
} }
/// @nodoc /// @nodoc
abstract class $WelcomeStateCopyWith<$Res> { abstract class $SplashStateCopyWith<$Res> {
factory $WelcomeStateCopyWith( factory $SplashStateCopyWith(
WelcomeState value, $Res Function(WelcomeState) then) = SplashState value, $Res Function(SplashState) then) =
_$WelcomeStateCopyWithImpl<$Res>; _$SplashStateCopyWithImpl<$Res>;
$Res call({AuthState auth}); $Res call({AuthState auth});
$AuthStateCopyWith<$Res> get auth; $AuthStateCopyWith<$Res> get auth;
} }
/// @nodoc /// @nodoc
class _$WelcomeStateCopyWithImpl<$Res> implements $WelcomeStateCopyWith<$Res> { class _$SplashStateCopyWithImpl<$Res> implements $SplashStateCopyWith<$Res> {
_$WelcomeStateCopyWithImpl(this._value, this._then); _$SplashStateCopyWithImpl(this._value, this._then);
final WelcomeState _value; final SplashState _value;
// ignore: unused_field // ignore: unused_field
final $Res Function(WelcomeState) _then; final $Res Function(SplashState) _then;
@override @override
$Res call({ $Res call({
@ -207,11 +207,11 @@ class _$WelcomeStateCopyWithImpl<$Res> implements $WelcomeStateCopyWith<$Res> {
} }
/// @nodoc /// @nodoc
abstract class _$WelcomeStateCopyWith<$Res> abstract class _$SplashStateCopyWith<$Res>
implements $WelcomeStateCopyWith<$Res> { implements $SplashStateCopyWith<$Res> {
factory _$WelcomeStateCopyWith( factory _$SplashStateCopyWith(
_WelcomeState value, $Res Function(_WelcomeState) then) = _SplashState value, $Res Function(_SplashState) then) =
__$WelcomeStateCopyWithImpl<$Res>; __$SplashStateCopyWithImpl<$Res>;
@override @override
$Res call({AuthState auth}); $Res call({AuthState auth});
@ -220,20 +220,20 @@ abstract class _$WelcomeStateCopyWith<$Res>
} }
/// @nodoc /// @nodoc
class __$WelcomeStateCopyWithImpl<$Res> extends _$WelcomeStateCopyWithImpl<$Res> class __$SplashStateCopyWithImpl<$Res> extends _$SplashStateCopyWithImpl<$Res>
implements _$WelcomeStateCopyWith<$Res> { implements _$SplashStateCopyWith<$Res> {
__$WelcomeStateCopyWithImpl( __$SplashStateCopyWithImpl(
_WelcomeState _value, $Res Function(_WelcomeState) _then) _SplashState _value, $Res Function(_SplashState) _then)
: super(_value, (v) => _then(v as _WelcomeState)); : super(_value, (v) => _then(v as _SplashState));
@override @override
_WelcomeState get _value => super._value as _WelcomeState; _SplashState get _value => super._value as _SplashState;
@override @override
$Res call({ $Res call({
Object? auth = freezed, Object? auth = freezed,
}) { }) {
return _then(_WelcomeState( return _then(_SplashState(
auth: auth == freezed auth: auth == freezed
? _value.auth ? _value.auth
: auth // ignore: cast_nullable_to_non_nullable : auth // ignore: cast_nullable_to_non_nullable
@ -244,21 +244,21 @@ class __$WelcomeStateCopyWithImpl<$Res> extends _$WelcomeStateCopyWithImpl<$Res>
/// @nodoc /// @nodoc
class _$_WelcomeState implements _WelcomeState { class _$_SplashState implements _SplashState {
const _$_WelcomeState({required this.auth}); const _$_SplashState({required this.auth});
@override @override
final AuthState auth; final AuthState auth;
@override @override
String toString() { String toString() {
return 'WelcomeState(auth: $auth)'; return 'SplashState(auth: $auth)';
} }
@override @override
bool operator ==(dynamic other) { bool operator ==(dynamic other) {
return identical(this, other) || return identical(this, other) ||
(other is _WelcomeState && (other is _SplashState &&
(identical(other.auth, auth) || (identical(other.auth, auth) ||
const DeepCollectionEquality().equals(other.auth, auth))); const DeepCollectionEquality().equals(other.auth, auth)));
} }
@ -269,17 +269,17 @@ class _$_WelcomeState implements _WelcomeState {
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
_$WelcomeStateCopyWith<_WelcomeState> get copyWith => _$SplashStateCopyWith<_SplashState> get copyWith =>
__$WelcomeStateCopyWithImpl<_WelcomeState>(this, _$identity); __$SplashStateCopyWithImpl<_SplashState>(this, _$identity);
} }
abstract class _WelcomeState implements WelcomeState { abstract class _SplashState implements SplashState {
const factory _WelcomeState({required AuthState auth}) = _$_WelcomeState; const factory _SplashState({required AuthState auth}) = _$_SplashState;
@override @override
AuthState get auth => throw _privateConstructorUsedError; AuthState get auth => throw _privateConstructorUsedError;
@override @override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$WelcomeStateCopyWith<_WelcomeState> get copyWith => _$SplashStateCopyWith<_SplashState> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
} }

View File

@ -3,11 +3,13 @@ import 'package:flutter/widgets.dart';
import 'auth_state.dart'; import 'auth_state.dart';
abstract class IWelcomeAuth { abstract class ISplashAuth {
Future<AuthState> currentUserProfile(); Future<AuthState> currentUserProfile();
} }
abstract class IWelcomeRoute { abstract class IWelcomeRoute {
Widget pushSignInScreen(); void pushSignInScreen(BuildContext context);
Future<void> pushHomeScreen(BuildContext context, UserProfile profile); Future<void> pushWelcomeScreen(BuildContext context, UserProfile profile);
void pushHomeScreen(
BuildContext context, UserProfile profile, String workspaceId);
} }

View File

@ -1,5 +1,5 @@
import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart'; import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart';
import 'package:app_flowy/welcome/application/welcome_bloc.dart'; import 'package:app_flowy/welcome/application/splash_bloc.dart';
import 'package:app_flowy/welcome/infrastructure/i_welcome_impl.dart'; import 'package:app_flowy/welcome/infrastructure/i_welcome_impl.dart';
import 'package:app_flowy/workspace/application/home/home_bloc.dart'; import 'package:app_flowy/workspace/application/home/home_bloc.dart';
import 'package:app_flowy/workspace/application/home/home_watcher_bloc.dart'; import 'package:app_flowy/workspace/application/home/home_watcher_bloc.dart';
@ -7,13 +7,12 @@ import 'package:get_it/get_it.dart';
class WelcomeDepsResolver { class WelcomeDepsResolver {
static Future<void> resolve(GetIt getIt) async { static Future<void> resolve(GetIt getIt) async {
getIt.registerFactory<IWelcomeAuth>(() => WelcomeAuthImpl()); getIt.registerFactory<ISplashAuth>(() => WelcomeAuthImpl());
getIt.registerFactory<IWelcomeRoute>(() => WelcomeRoute()); getIt.registerFactory<IWelcomeRoute>(() => WelcomeRoute());
getIt.registerFactory<HomeBloc>(() => HomeBloc()); getIt.registerFactory<HomeBloc>(() => HomeBloc());
getIt.registerFactory<HomeWatcherBloc>(() => HomeWatcherBloc()); getIt.registerFactory<HomeWatcherBloc>(() => HomeWatcherBloc());
getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc()); getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
getIt getIt.registerFactory<SplashBloc>(() => SplashBloc(getIt<ISplashAuth>()));
.registerFactory<WelcomeBloc>(() => WelcomeBloc(getIt<IWelcomeAuth>()));
} }
} }

View File

@ -1,29 +1,28 @@
import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/startup/startup.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/sign_in_screen.dart'; import 'package:app_flowy/user/presentation/sign_in_screen.dart';
import 'package:app_flowy/welcome/domain/auth_state.dart'; import 'package:app_flowy/welcome/domain/auth_state.dart';
import 'package:app_flowy/welcome/domain/i_welcome.dart'; import 'package:app_flowy/welcome/domain/i_welcome.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/home/home_screen.dart'; import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
import 'package:app_flowy/workspace/presentation/workspace/workspace_select_screen.dart'; import 'package:app_flowy/welcome/presentation/welcome_screen.dart';
import 'package:flowy_infra/time/duration.dart'; import 'package:flowy_infra/time/duration.dart';
import 'package:flowy_infra_ui/widget/route/animation.dart'; import 'package:flowy_infra_ui/widget/route/animation.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart' as workspace;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
export 'package:app_flowy/welcome/domain/i_welcome.dart'; export 'package:app_flowy/welcome/domain/i_welcome.dart';
class WelcomeAuthImpl implements IWelcomeAuth { class WelcomeAuthImpl implements ISplashAuth {
@override @override
Future<AuthState> currentUserProfile() { Future<AuthState> currentUserProfile() {
final result = UserEventGetUserProfile().send(); final result = UserEventGetUserProfile().send();
return result.then((result) { return result.then((result) {
return result.fold( return result.fold(
(UserProfile) { (userProfile) {
return AuthState.authenticated(UserProfile); return AuthState.authenticated(userProfile);
}, },
(userError) { (userError) {
return AuthState.unauthenticated(userError); return AuthState.unauthenticated(userError);
@ -35,39 +34,35 @@ class WelcomeAuthImpl implements IWelcomeAuth {
class WelcomeRoute implements IWelcomeRoute { class WelcomeRoute implements IWelcomeRoute {
@override @override
Future<void> pushHomeScreen(BuildContext context, UserProfile user) async { Future<void> pushWelcomeScreen(BuildContext context, UserProfile user) async {
final repo = UserRepo(user: user); final repo = UserRepo(user: user);
return WorkspaceEventReadCurWorkspace().send().then( final screen = WelcomeScreen(repo: repo);
(result) { final workspaceId = await Navigator.of(context).push(
return result.fold( PageRoutes.fade(
(workspace) => () => screen,
_pushToScreen(context, HomeScreen(repo.user, workspace.id)), RouteDurations.slow.inMilliseconds * .001,
(error) async { ),
assert(error.code == workspace.ErrorCode.CurrentWorkspaceNotFound); );
final screen = WorkspaceSelectScreen(repo: repo);
final workspaceId = await Navigator.of(context).push(
PageRoutes.fade(
() => screen,
RouteDurations.slow.inMilliseconds * .001,
),
);
_pushToScreen(context, HomeScreen(repo.user, workspaceId)); pushHomeScreen(context, repo.user, workspaceId);
}, }
);
}, @override
void pushHomeScreen(
BuildContext context, UserProfile userProfile, String workspaceId) {
Navigator.push(
context,
PageRoutes.fade(() => HomeScreen(userProfile, workspaceId),
RouteDurations.slow.inMilliseconds * .001),
); );
} }
@override @override
Widget pushSignInScreen() { void pushSignInScreen(BuildContext context) {
return SignInScreen(router: getIt<IAuthRouter>());
}
void _pushToScreen(BuildContext context, Widget screen) {
Navigator.push( Navigator.push(
context, context,
PageRoutes.fade( PageRoutes.fade(() => SignInScreen(router: getIt<IAuthRouter>()),
() => screen, RouteDurations.slow.inMilliseconds * .001)); RouteDurations.slow.inMilliseconds * .001),
);
} }
} }

View File

@ -0,0 +1,81 @@
import 'package:app_flowy/welcome/domain/i_welcome.dart';
import 'package:app_flowy/welcome/domain/auth_state.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/welcome/application/splash_bloc.dart';
import 'package:flowy_infra/flowy_logger.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart' as workspace;
class SplashScreen extends StatelessWidget {
const SplashScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) {
return getIt<SplashBloc>()..add(const SplashEvent.getUser());
},
child: Scaffold(
body: BlocListener<SplashBloc, SplashState>(
listener: (context, state) {
state.auth.map(
authenticated: (r) => _handleAuthenticated(context, r),
unauthenticated: (r) => _handleUnauthenticated(context, r),
initial: (r) => {},
);
},
child: const Body(),
),
),
);
}
void _handleAuthenticated(BuildContext context, Authenticated result) {
final userProfile = result.userProfile;
WorkspaceEventReadCurWorkspace().send().then(
(result) {
return result.fold(
(workspace) => getIt<IWelcomeRoute>()
.pushHomeScreen(context, userProfile, workspace.id),
(error) async {
assert(error.code == workspace.ErrorCode.CurrentWorkspaceNotFound);
getIt<IWelcomeRoute>().pushWelcomeScreen(context, userProfile);
},
);
},
);
}
void _handleUnauthenticated(BuildContext context, Unauthenticated result) {
Log.error(result.error);
getIt<IWelcomeRoute>().pushSignInScreen(context);
}
}
class Body extends StatelessWidget {
const Body({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return Container(
alignment: Alignment.center,
child: SingleChildScrollView(
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')),
const CircularProgressIndicator.adaptive(),
],
),
),
);
}
}

View File

@ -1,77 +1,105 @@
import 'package:app_flowy/welcome/domain/i_welcome.dart'; import 'package:app_flowy/workspace/application/workspace/workspace_list_bloc.dart';
import 'package:app_flowy/welcome/domain/auth_state.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
import 'package:app_flowy/startup/startup.dart'; import 'package:flowy_infra_ui/style_widget/text_button.dart';
import 'package:app_flowy/welcome/application/welcome_bloc.dart'; import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_infra_ui/widget/route/animation.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
import 'package:flowy_infra/flowy_logger.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:flowy_infra/time/prelude.dart'; import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
class WelcomeScreen extends StatelessWidget { class WelcomeScreen extends StatelessWidget {
const WelcomeScreen({Key? key}) : super(key: key); final UserRepo repo;
const WelcomeScreen({
Key? key,
required this.repo,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) { create: (_) =>
return getIt<WelcomeBloc>()..add(const WelcomeEvent.getUser()); WorkspaceListBloc(repo)..add(const WorkspaceListEvent.initial()),
}, child: BlocBuilder<WorkspaceListBloc, WorkspaceListState>(
child: Scaffold( builder: (context, state) {
body: BlocListener<WelcomeBloc, WelcomeState>( return Scaffold(
listener: (context, state) { body: Padding(
state.auth.map( padding: const EdgeInsets.all(60.0),
authenticated: (r) => _handleAuthenticated(context, r), child: Column(
unauthenticated: (r) => _handleUnauthenticated(context, r), children: [
initial: (r) => {}, _renderBody(state),
); _renderCreateButton(context),
}, ],
child: const Body(), ),
), ),
);
},
), ),
); );
} }
void _pushToScreen(BuildContext context, Widget screen) { Widget _renderBody(WorkspaceListState state) {
/// Let the splash view sit for a bit. Mainly for aesthetics and to ensure a smooth intro animation. final body = state.successOrFailure.fold(
Navigator.push( (_) => _renderList(state.workspaces),
context, (error) => FlowyErrorPage(error.toString()),
PageRoutes.fade( );
() => screen, RouteDurations.slow.inMilliseconds * .001)); return body;
} }
void _handleAuthenticated(BuildContext context, Authenticated result) { Widget _renderCreateButton(BuildContext context) {
getIt<IWelcomeRoute>().pushHomeScreen(context, result.userProfile); return SizedBox(
width: 200,
height: 40,
child: FlowyTextButton(
"Create workspace",
fontSize: 14,
onPressed: () {
context
.read<WorkspaceListBloc>()
.add(const WorkspaceListEvent.createWorkspace("workspace", ""));
},
),
);
} }
void _handleUnauthenticated(BuildContext context, Unauthenticated result) { Widget _renderList(List<Workspace> workspaces) {
Log.error(result.error); return Expanded(
child: StyledListView(
itemBuilder: (BuildContext context, int index) {
final workspace = workspaces[index];
return WorkspaceItem(
workspace: workspace,
onPressed: (workspace) => _handleOnPress(context, workspace),
);
},
itemCount: workspaces.length,
),
);
}
_pushToScreen(context, getIt<IWelcomeRoute>().pushSignInScreen()); void _handleOnPress(BuildContext context, Workspace workspace) {
context
.read<WorkspaceListBloc>()
.add(WorkspaceListEvent.openWorkspace(workspace));
Navigator.of(context).pop(workspace.id);
} }
} }
class Body extends StatelessWidget { class WorkspaceItem extends StatelessWidget {
const Body({Key? key}) : super(key: key); final Workspace workspace;
final void Function(Workspace workspace) onPressed;
const WorkspaceItem(
{Key? key, required this.workspace, required this.onPressed})
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var size = MediaQuery.of(context).size; return SizedBox(
height: 46,
return Container( child: FlowyTextButton(
alignment: Alignment.center, workspace.name,
child: SingleChildScrollView( fontSize: 14,
child: Stack( onPressed: () => onPressed(workspace),
alignment: Alignment.center,
children: [
Image(
fit: BoxFit.cover,
width: size.width,
height: size.height,
image: const AssetImage(
'assets/images/appflowy_launch_splash.jpg')),
const CircularProgressIndicator.adaptive(),
],
),
), ),
); );
} }

View File

@ -1,236 +0,0 @@
import 'package:app_flowy/workspace/application/workspace/workspace_list_bloc.dart';
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
import 'package:flowy_infra_ui/style_widget/text_button.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
class WorkspaceSelectScreen extends StatelessWidget {
final UserRepo repo;
const WorkspaceSelectScreen({
Key? key,
required this.repo,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) =>
WorkspaceListBloc(repo)..add(const WorkspaceListEvent.initial()),
child: BlocBuilder<WorkspaceListBloc, WorkspaceListState>(
builder: (context, state) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(60.0),
child: Column(
children: [
_renderBody(state),
_renderCreateButton(context),
],
),
),
);
},
),
);
}
Widget _renderBody(WorkspaceListState state) {
final body = state.successOrFailure.fold(
(_) => _renderList(state.workspaces),
(error) => FlowyErrorPage(error.toString()),
);
return body;
}
Widget _renderCreateButton(BuildContext context) {
return SizedBox(
width: 200,
height: 40,
child: FlowyTextButton(
"Create workspace",
fontSize: 14,
onPressed: () {
context
.read<WorkspaceListBloc>()
.add(const WorkspaceListEvent.createWorkspace("workspace", ""));
},
),
);
}
Widget _renderList(List<Workspace> workspaces) {
return Expanded(
child: StyledListView(
itemBuilder: (BuildContext context, int index) {
final workspace = workspaces[index];
return WorkspaceItem(
workspace: workspace,
onPressed: (workspace) => _handleOnPress(context, workspace),
);
},
itemCount: workspaces.length,
),
);
}
void _handleOnPress(BuildContext context, Workspace workspace) {
context
.read<WorkspaceListBloc>()
.add(WorkspaceListEvent.openWorkspace(workspace));
Navigator.of(context).pop(workspace.id);
}
}
class WorkspaceItem extends StatelessWidget {
final Workspace workspace;
final void Function(Workspace workspace) onPressed;
const WorkspaceItem(
{Key? key, required this.workspace, required this.onPressed})
: super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
height: 46,
child: FlowyTextButton(
workspace.name,
fontSize: 14,
onPressed: () => onPressed(workspace),
),
);
}
}
// Bloc and Provider
// *************Provider***************
// class WorkspaceListNotifier with ChangeNotifier {
// UserRepo repo;
// List<Workspace> workspaces = [];
// WorkspaceListNotifier({
// required this.repo,
// }) {
// fetch();
// }
// void fetch() {
// repo.fetchWorkspaces().then((result) {
// result.fold((workspaces) {
// this.workspaces = workspaces;
// notifyListeners();
// }, (error) {
// Log.error(error);
// });
// });
// }
// }
// class WorkspaceSelectScreen extends StatelessWidget {
// final UserProfile user;
// const WorkspaceSelectScreen({
// Key? key,
// required this.user,
// }) : super(key: key);
// @override
// Widget build(BuildContext context) {
// return MultiProvider(
// providers: [
// ChangeNotifierProvider(
// create: (_) => WorkspaceListNotifier(repo: UserRepo(user: user)),
// )
// ],
// child: Consumer<WorkspaceListNotifier>(builder: (ctx, notifier, child) {
// return StyledListView(
// itemBuilder: (BuildContext context, int index) {
// final workspace = notifier.workspaces[index];
// return WorkspaceItem(workspace);
// },
// itemCount: notifier.workspaces.length,
// );
// }));
// }
// }
// *************Bloc***************
//
// class WorkspaceListBloc extends Bloc<WorkspaceListEvent, WorkspaceListState> {
// UserRepo repo;
// WorkspaceListBloc(this.repo) : super(WorkspaceListState.initial());
// @override
// Stream<WorkspaceListState> mapEventToState(
// WorkspaceListEvent event,
// ) async* {
// yield* event.map(
// initial: (e) async* {
// yield* _fetchWorkspaces();
// },
// );
// }
// Stream<WorkspaceListState> _fetchWorkspaces() async* {
// final workspacesOrFailed = await repo.fetchWorkspaces();
// yield workspacesOrFailed.fold(
// (workspaces) => state.copyWith(
// workspaces: workspaces, successOrFailure: left(unit)),
// (error) => state.copyWith(successOrFailure: right(error)));
// }
// }
// @freezed
// abstract class WorkspaceListEvent with _$WorkspaceListEvent {
// const factory WorkspaceListEvent.initial() = Initial;
// }
// @freezed
// abstract class WorkspaceListState implements _$WorkspaceListState {
// const factory WorkspaceListState({
// required bool isLoading,
// required List<Workspace> workspaces,
// required Either<Unit, WorkspaceError> successOrFailure,
// }) = _WorkspaceListState;
// factory WorkspaceListState.initial() => WorkspaceListState(
// isLoading: false,
// workspaces: List.empty(),
// successOrFailure: left(unit),
// );
// }
//
// class WorkspaceSelectScreen extends StatelessWidget {
// final UserProfile user;
// const WorkspaceSelectScreen({
// Key? key,
// required this.user,
// }) : super(key: key);
// @override
// Widget build(BuildContext context) {
// return BlocProvider(
// create: (_) => WorkspaceListBloc(UserRepo(user: user))
// ..add(const WorkspaceListEvent.initial()),
// child: BlocBuilder<WorkspaceListBloc, WorkspaceListState>(
// builder: (context, state) {
// return state.successOrFailure.fold(
// (_) => StyledListView(
// itemBuilder: (BuildContext context, int index) {
// final workspace = state.workspaces[index];
// return WorkspaceItem(workspace);
// },
// itemCount: state.workspaces.length,
// ),
// (error) => Container(),
// );
// },
// ),
// );
// }
// }

View File

@ -8,7 +8,7 @@ class Log {
Log() { Log() {
_logger = Logger( _logger = Logger(
printer: PrettyPrinter( printer: PrettyPrinter(
methodCount: 2, // number of method calls to be displayed methodCount: 0, // number of method calls to be displayed
errorMethodCount: errorMethodCount:
8, // number of method calls if stacktrace is provided 8, // number of method calls if stacktrace is provided
lineLength: 120, // width of the output lineLength: 120, // width of the output

View File

@ -85,13 +85,18 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
]; ];
if (widget.errorText.isNotEmpty) { if (widget.errorText.isNotEmpty) {
children.add(Text( children.add(
widget.errorText, Align(
style: TextStyle( alignment: Alignment.centerLeft,
color: widget.highlightBorderColor, child: Text(
fontWeight: widget.fontWeight, widget.errorText,
fontSize: widget.fontSize), style: TextStyle(
)); color: widget.highlightBorderColor,
fontWeight: widget.fontWeight,
fontSize: widget.fontSize),
),
),
);
} }
return AnimatedSize( return AnimatedSize(

View File

@ -16,6 +16,7 @@ class WorkspaceObservable extends $pb.ProtobufEnum {
static const WorkspaceObservable WorkspaceUpdated = WorkspaceObservable._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceUpdated'); static const WorkspaceObservable WorkspaceUpdated = WorkspaceObservable._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceUpdated');
static const WorkspaceObservable WorkspaceCreateApp = WorkspaceObservable._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceCreateApp'); static const WorkspaceObservable WorkspaceCreateApp = WorkspaceObservable._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceCreateApp');
static const WorkspaceObservable WorkspaceDeleteApp = WorkspaceObservable._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDeleteApp'); static const WorkspaceObservable WorkspaceDeleteApp = WorkspaceObservable._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDeleteApp');
static const WorkspaceObservable WorkspaceListUpdated = WorkspaceObservable._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceListUpdated');
static const WorkspaceObservable AppUpdated = WorkspaceObservable._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppUpdated'); static const WorkspaceObservable AppUpdated = WorkspaceObservable._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppUpdated');
static const WorkspaceObservable AppCreateView = WorkspaceObservable._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppCreateView'); static const WorkspaceObservable AppCreateView = WorkspaceObservable._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppCreateView');
static const WorkspaceObservable AppDeleteView = WorkspaceObservable._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppDeleteView'); static const WorkspaceObservable AppDeleteView = WorkspaceObservable._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppDeleteView');
@ -28,6 +29,7 @@ class WorkspaceObservable extends $pb.ProtobufEnum {
WorkspaceUpdated, WorkspaceUpdated,
WorkspaceCreateApp, WorkspaceCreateApp,
WorkspaceDeleteApp, WorkspaceDeleteApp,
WorkspaceListUpdated,
AppUpdated, AppUpdated,
AppCreateView, AppCreateView,
AppDeleteView, AppDeleteView,

View File

@ -18,6 +18,7 @@ const WorkspaceObservable$json = const {
const {'1': 'WorkspaceUpdated', '2': 12}, const {'1': 'WorkspaceUpdated', '2': 12},
const {'1': 'WorkspaceCreateApp', '2': 13}, const {'1': 'WorkspaceCreateApp', '2': 13},
const {'1': 'WorkspaceDeleteApp', '2': 14}, const {'1': 'WorkspaceDeleteApp', '2': 14},
const {'1': 'WorkspaceListUpdated', '2': 15},
const {'1': 'AppUpdated', '2': 21}, const {'1': 'AppUpdated', '2': 21},
const {'1': 'AppCreateView', '2': 23}, const {'1': 'AppCreateView', '2': 23},
const {'1': 'AppDeleteView', '2': 24}, const {'1': 'AppDeleteView', '2': 24},
@ -26,4 +27,4 @@ const WorkspaceObservable$json = const {
}; };
/// Descriptor for `WorkspaceObservable`. Decode as a `google.protobuf.EnumDescriptorProto`. /// Descriptor for `WorkspaceObservable`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List workspaceObservableDescriptor = $convert.base64Decode('ChNXb3Jrc3BhY2VPYnNlcnZhYmxlEgsKB1Vua25vd24QABIXChNVc2VyQ3JlYXRlV29ya3NwYWNlEAoSFwoTVXNlckRlbGV0ZVdvcmtzcGFjZRALEhQKEFdvcmtzcGFjZVVwZGF0ZWQQDBIWChJXb3Jrc3BhY2VDcmVhdGVBcHAQDRIWChJXb3Jrc3BhY2VEZWxldGVBcHAQDhIOCgpBcHBVcGRhdGVkEBUSEQoNQXBwQ3JlYXRlVmlldxAXEhEKDUFwcERlbGV0ZVZpZXcQGBIPCgtWaWV3VXBkYXRlZBAf'); final $typed_data.Uint8List workspaceObservableDescriptor = $convert.base64Decode('ChNXb3Jrc3BhY2VPYnNlcnZhYmxlEgsKB1Vua25vd24QABIXChNVc2VyQ3JlYXRlV29ya3NwYWNlEAoSFwoTVXNlckRlbGV0ZVdvcmtzcGFjZRALEhQKEFdvcmtzcGFjZVVwZGF0ZWQQDBIWChJXb3Jrc3BhY2VDcmVhdGVBcHAQDRIWChJXb3Jrc3BhY2VEZWxldGVBcHAQDhIYChRXb3Jrc3BhY2VMaXN0VXBkYXRlZBAPEg4KCkFwcFVwZGF0ZWQQFRIRCg1BcHBDcmVhdGVWaWV3EBcSEQoNQXBwRGVsZXRlVmlldxAYEg8KC1ZpZXdVcGRhdGVkEB8=');

View File

@ -182,6 +182,7 @@ async fn configure_database(config: &DatabaseSettings) -> PgPool {
} }
async fn drop_test_database(database_name: String) { async fn drop_test_database(database_name: String) {
// https://stackoverflow.com/questions/36502401/postgres-drop-database-error-pq-cannot-drop-the-currently-open-database?rq=1
let configuration = { let configuration = {
let mut c = get_configuration().expect("Failed to read configuration."); let mut c = get_configuration().expect("Failed to read configuration.");
c.database.database_name = "flowy".to_owned(); c.database.database_name = "flowy".to_owned();

View File

@ -24,7 +24,7 @@ pub extern "C" fn init_sdk(path: *mut c_char) -> i64 {
let c_str: &CStr = unsafe { CStr::from_ptr(path) }; let c_str: &CStr = unsafe { CStr::from_ptr(path) };
let path: &str = c_str.to_str().unwrap(); let path: &str = c_str.to_str().unwrap();
let config = FlowySDKConfig::new(path).log_filter("info"); let config = FlowySDKConfig::new(path).log_filter("debug");
*FLOWY_SDK.write() = Some(Arc::new(FlowySDK::new(config))); *FLOWY_SDK.write() = Some(Arc::new(FlowySDK::new(config)));
return 1; return 1;

View File

@ -11,7 +11,7 @@ pub struct SignInRequest {
pub password: String, pub password: String,
} }
#[derive(Default, ProtoBuf)] #[derive(Default, ProtoBuf, Debug)]
pub struct SignInParams { pub struct SignInParams {
#[pb(index = 1)] #[pb(index = 1)]
pub email: String, pub email: String,
@ -76,7 +76,7 @@ impl TryInto<SignUpParams> for SignUpRequest {
} }
} }
#[derive(ProtoBuf, Default)] #[derive(ProtoBuf, Default, Debug)]
pub struct SignUpParams { pub struct SignUpParams {
#[pb(index = 1)] #[pb(index = 1)]
pub email: String, pub email: String,

View File

@ -85,7 +85,7 @@ impl UpdateUserRequest {
} }
} }
#[derive(ProtoBuf, Default, Clone)] #[derive(ProtoBuf, Default, Clone, Debug)]
pub struct UpdateUserParams { pub struct UpdateUserParams {
// TODO: remove user id // TODO: remove user id
#[pb(index = 1)] #[pb(index = 1)]

View File

@ -1298,60 +1298,60 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x05email\x12\x1c\n\x08password\x18\x04\x20\x01(\tH\x02R\x08passwordB\r\ \x05email\x12\x1c\n\x08password\x18\x04\x20\x01(\tH\x02R\x08passwordB\r\
\n\x0bone_of_nameB\x0e\n\x0cone_of_emailB\x11\n\x0fone_of_password*1\n\n\ \n\x0bone_of_nameB\x0e\n\x0cone_of_emailB\x11\n\x0fone_of_password*1\n\n\
UserStatus\x12\x0b\n\x07Unknown\x10\0\x12\t\n\x05Login\x10\x01\x12\x0b\n\ UserStatus\x12\x0b\n\x07Unknown\x10\0\x12\t\n\x05Login\x10\x01\x12\x0b\n\
\x07Expired\x10\x02J\xbb\x08\n\x06\x12\x04\0\0\x19\x01\n\x08\n\x01\x0c\ \x07Expired\x10\x02J\xbb\x08\n\x06\x12\x04\0\0\x1a\x01\n\x08\n\x01\x0c\
\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x01\0\x03\x01\n\n\n\x03\x04\0\ \x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\n\n\x03\x04\0\
\x01\x12\x03\x01\x08\x11\n\x0b\n\x04\x04\0\x02\0\x12\x03\x02\x04\x15\n\ \x01\x12\x03\x02\x08\x11\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x15\n\
\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x02\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\ \x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\
\x12\x03\x02\x0b\x10\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x02\x13\x14\n\n\ \x12\x03\x03\x0b\x10\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x13\x14\n\n\
\n\x02\x04\x01\x12\x04\x04\0\x08\x01\n\n\n\x03\x04\x01\x01\x12\x03\x04\ \n\x02\x04\x01\x12\x04\x05\0\t\x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\x08\
\x08\x13\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x05\x04\x12\n\x0c\n\x05\x04\ \x13\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x06\x04\x12\n\x0c\n\x05\x04\x01\
\x01\x02\0\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\ \x02\0\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x06\
\x05\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x05\x10\x11\n\x0b\n\x04\ \x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x06\x10\x11\n\x0b\n\x04\x04\
\x04\x01\x02\x01\x12\x03\x06\x04\x15\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\ \x01\x02\x01\x12\x03\x07\x04\x15\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\
\x03\x06\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x06\x0b\x10\n\x0c\ \x07\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x07\x0b\x10\n\x0c\n\
\n\x05\x04\x01\x02\x01\x03\x12\x03\x06\x13\x14\n\x0b\n\x04\x04\x01\x02\ \x05\x04\x01\x02\x01\x03\x12\x03\x07\x13\x14\n\x0b\n\x04\x04\x01\x02\x02\
\x02\x12\x03\x07\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x07\x04\ \x12\x03\x08\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x08\x04\n\n\
\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x07\x0b\x0f\n\x0c\n\x05\x04\ \x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x08\x0b\x0f\n\x0c\n\x05\x04\x01\
\x01\x02\x02\x03\x12\x03\x07\x12\x13\n\n\n\x02\x04\x02\x12\x04\t\0\x0e\ \x02\x02\x03\x12\x03\x08\x12\x13\n\n\n\x02\x04\x02\x12\x04\n\0\x0f\x01\n\
\x01\n\n\n\x03\x04\x02\x01\x12\x03\t\x08\x19\n\x0b\n\x04\x04\x02\x02\0\ \n\n\x03\x04\x02\x01\x12\x03\n\x08\x19\n\x0b\n\x04\x04\x02\x02\0\x12\x03\
\x12\x03\n\x04\x12\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\ \x0b\x04\x12\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0b\x04\n\n\x0c\n\x05\
\x05\x04\x02\x02\0\x01\x12\x03\n\x0b\r\n\x0c\n\x05\x04\x02\x02\0\x03\x12\ \x04\x02\x02\0\x01\x12\x03\x0b\x0b\r\n\x0c\n\x05\x04\x02\x02\0\x03\x12\
\x03\n\x10\x11\n\x0b\n\x04\x04\x02\x08\0\x12\x03\x0b\x04*\n\x0c\n\x05\ \x03\x0b\x10\x11\n\x0b\n\x04\x04\x02\x08\0\x12\x03\x0c\x04*\n\x0c\n\x05\
\x04\x02\x08\0\x01\x12\x03\x0b\n\x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\ \x04\x02\x08\0\x01\x12\x03\x0c\n\x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\
\x0b\x18(\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\x0b\x18\x1e\n\x0c\n\ \x0c\x18(\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\x0c\x18\x1e\n\x0c\n\
\x05\x04\x02\x02\x01\x01\x12\x03\x0b\x1f#\n\x0c\n\x05\x04\x02\x02\x01\ \x05\x04\x02\x02\x01\x01\x12\x03\x0c\x1f#\n\x0c\n\x05\x04\x02\x02\x01\
\x03\x12\x03\x0b&'\n\x0b\n\x04\x04\x02\x08\x01\x12\x03\x0c\x04,\n\x0c\n\ \x03\x12\x03\x0c&'\n\x0b\n\x04\x04\x02\x08\x01\x12\x03\r\x04,\n\x0c\n\
\x05\x04\x02\x08\x01\x01\x12\x03\x0c\n\x16\n\x0b\n\x04\x04\x02\x02\x02\ \x05\x04\x02\x08\x01\x01\x12\x03\r\n\x16\n\x0b\n\x04\x04\x02\x02\x02\x12\
\x12\x03\x0c\x19*\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\x0c\x19\x1f\n\ \x03\r\x19*\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\r\x19\x1f\n\x0c\n\
\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x0c\x20%\n\x0c\n\x05\x04\x02\x02\ \x05\x04\x02\x02\x02\x01\x12\x03\r\x20%\n\x0c\n\x05\x04\x02\x02\x02\x03\
\x02\x03\x12\x03\x0c()\n\x0b\n\x04\x04\x02\x08\x02\x12\x03\r\x042\n\x0c\ \x12\x03\r()\n\x0b\n\x04\x04\x02\x08\x02\x12\x03\x0e\x042\n\x0c\n\x05\
\n\x05\x04\x02\x08\x02\x01\x12\x03\r\n\x19\n\x0b\n\x04\x04\x02\x02\x03\ \x04\x02\x08\x02\x01\x12\x03\x0e\n\x19\n\x0b\n\x04\x04\x02\x02\x03\x12\
\x12\x03\r\x1c0\n\x0c\n\x05\x04\x02\x02\x03\x05\x12\x03\r\x1c\"\n\x0c\n\ \x03\x0e\x1c0\n\x0c\n\x05\x04\x02\x02\x03\x05\x12\x03\x0e\x1c\"\n\x0c\n\
\x05\x04\x02\x02\x03\x01\x12\x03\r#+\n\x0c\n\x05\x04\x02\x02\x03\x03\x12\ \x05\x04\x02\x02\x03\x01\x12\x03\x0e#+\n\x0c\n\x05\x04\x02\x02\x03\x03\
\x03\r./\n\n\n\x02\x04\x03\x12\x04\x0f\0\x14\x01\n\n\n\x03\x04\x03\x01\ \x12\x03\x0e./\n\n\n\x02\x04\x03\x12\x04\x10\0\x15\x01\n\n\n\x03\x04\x03\
\x12\x03\x0f\x08\x18\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x10\x04\x12\n\x0c\ \x01\x12\x03\x10\x08\x18\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x11\x04\x12\n\
\n\x05\x04\x03\x02\0\x05\x12\x03\x10\x04\n\n\x0c\n\x05\x04\x03\x02\0\x01\ \x0c\n\x05\x04\x03\x02\0\x05\x12\x03\x11\x04\n\n\x0c\n\x05\x04\x03\x02\0\
\x12\x03\x10\x0b\r\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x10\x10\x11\n\ \x01\x12\x03\x11\x0b\r\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x11\x10\x11\
\x0b\n\x04\x04\x03\x08\0\x12\x03\x11\x04*\n\x0c\n\x05\x04\x03\x08\0\x01\ \n\x0b\n\x04\x04\x03\x08\0\x12\x03\x12\x04*\n\x0c\n\x05\x04\x03\x08\0\
\x12\x03\x11\n\x15\n\x0b\n\x04\x04\x03\x02\x01\x12\x03\x11\x18(\n\x0c\n\ \x01\x12\x03\x12\n\x15\n\x0b\n\x04\x04\x03\x02\x01\x12\x03\x12\x18(\n\
\x05\x04\x03\x02\x01\x05\x12\x03\x11\x18\x1e\n\x0c\n\x05\x04\x03\x02\x01\ \x0c\n\x05\x04\x03\x02\x01\x05\x12\x03\x12\x18\x1e\n\x0c\n\x05\x04\x03\
\x01\x12\x03\x11\x1f#\n\x0c\n\x05\x04\x03\x02\x01\x03\x12\x03\x11&'\n\ \x02\x01\x01\x12\x03\x12\x1f#\n\x0c\n\x05\x04\x03\x02\x01\x03\x12\x03\
\x0b\n\x04\x04\x03\x08\x01\x12\x03\x12\x04,\n\x0c\n\x05\x04\x03\x08\x01\ \x12&'\n\x0b\n\x04\x04\x03\x08\x01\x12\x03\x13\x04,\n\x0c\n\x05\x04\x03\
\x01\x12\x03\x12\n\x16\n\x0b\n\x04\x04\x03\x02\x02\x12\x03\x12\x19*\n\ \x08\x01\x01\x12\x03\x13\n\x16\n\x0b\n\x04\x04\x03\x02\x02\x12\x03\x13\
\x0c\n\x05\x04\x03\x02\x02\x05\x12\x03\x12\x19\x1f\n\x0c\n\x05\x04\x03\ \x19*\n\x0c\n\x05\x04\x03\x02\x02\x05\x12\x03\x13\x19\x1f\n\x0c\n\x05\
\x02\x02\x01\x12\x03\x12\x20%\n\x0c\n\x05\x04\x03\x02\x02\x03\x12\x03\ \x04\x03\x02\x02\x01\x12\x03\x13\x20%\n\x0c\n\x05\x04\x03\x02\x02\x03\
\x12()\n\x0b\n\x04\x04\x03\x08\x02\x12\x03\x13\x042\n\x0c\n\x05\x04\x03\ \x12\x03\x13()\n\x0b\n\x04\x04\x03\x08\x02\x12\x03\x14\x042\n\x0c\n\x05\
\x08\x02\x01\x12\x03\x13\n\x19\n\x0b\n\x04\x04\x03\x02\x03\x12\x03\x13\ \x04\x03\x08\x02\x01\x12\x03\x14\n\x19\n\x0b\n\x04\x04\x03\x02\x03\x12\
\x1c0\n\x0c\n\x05\x04\x03\x02\x03\x05\x12\x03\x13\x1c\"\n\x0c\n\x05\x04\ \x03\x14\x1c0\n\x0c\n\x05\x04\x03\x02\x03\x05\x12\x03\x14\x1c\"\n\x0c\n\
\x03\x02\x03\x01\x12\x03\x13#+\n\x0c\n\x05\x04\x03\x02\x03\x03\x12\x03\ \x05\x04\x03\x02\x03\x01\x12\x03\x14#+\n\x0c\n\x05\x04\x03\x02\x03\x03\
\x13./\n\n\n\x02\x05\0\x12\x04\x15\0\x19\x01\n\n\n\x03\x05\0\x01\x12\x03\ \x12\x03\x14./\n\n\n\x02\x05\0\x12\x04\x16\0\x1a\x01\n\n\n\x03\x05\0\x01\
\x15\x05\x0f\n\x0b\n\x04\x05\0\x02\0\x12\x03\x16\x04\x10\n\x0c\n\x05\x05\ \x12\x03\x16\x05\x0f\n\x0b\n\x04\x05\0\x02\0\x12\x03\x17\x04\x10\n\x0c\n\
\0\x02\0\x01\x12\x03\x16\x04\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x16\ \x05\x05\0\x02\0\x01\x12\x03\x17\x04\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\
\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x17\x04\x0e\n\x0c\n\x05\x05\0\ \x03\x17\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x18\x04\x0e\n\x0c\n\
\x02\x01\x01\x12\x03\x17\x04\t\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x17\ \x05\x05\0\x02\x01\x01\x12\x03\x18\x04\t\n\x0c\n\x05\x05\0\x02\x01\x02\
\x0c\r\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x18\x04\x10\n\x0c\n\x05\x05\0\ \x12\x03\x18\x0c\r\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x19\x04\x10\n\x0c\n\
\x02\x02\x01\x12\x03\x18\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\ \x05\x05\0\x02\x02\x01\x12\x03\x19\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\
\x18\x0e\x0fb\x06proto3\ \x12\x03\x19\x0e\x0fb\x06proto3\
"; ";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -1,4 +1,5 @@
syntax = "proto3"; syntax = "proto3";
message UserToken { message UserToken {
string token = 1; string token = 1;
} }

View File

@ -1,12 +0,0 @@
use std::future::Future;
pub async fn spawn<F>(f: F)
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
match tokio::spawn(f).await {
Ok(_) => {},
Err(e) => log::error!("{:?}", e),
}
}

View File

@ -1,3 +1,2 @@
mod helper;
mod server; mod server;
pub mod user; pub mod user;

View File

@ -18,8 +18,6 @@ use flowy_infra::kv::KV;
use flowy_sqlite::ConnectionPool; use flowy_sqlite::ConnectionPool;
use parking_lot::RwLock; use parking_lot::RwLock;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::services::helper::spawn;
use std::sync::Arc; use std::sync::Arc;
pub struct UserSessionConfig { pub struct UserSessionConfig {
@ -70,6 +68,7 @@ impl UserSession {
self.database.get_pool(&user_id) self.database.get_pool(&user_id)
} }
#[tracing::instrument(level = "debug", skip(self))]
pub async fn sign_in(&self, params: SignInParams) -> Result<UserProfile, UserError> { pub async fn sign_in(&self, params: SignInParams) -> Result<UserProfile, UserError> {
if self.is_login(&params.email) { if self.is_login(&params.email) {
self.user_profile().await self.user_profile().await
@ -83,6 +82,7 @@ impl UserSession {
} }
} }
#[tracing::instrument(level = "debug", skip(self))]
pub async fn sign_up(&self, params: SignUpParams) -> Result<UserProfile, UserError> { pub async fn sign_up(&self, params: SignUpParams) -> Result<UserProfile, UserError> {
if self.is_login(&params.email) { if self.is_login(&params.email) {
self.user_profile().await self.user_profile().await
@ -96,6 +96,7 @@ impl UserSession {
} }
} }
#[tracing::instrument(level = "debug", skip(self))]
pub async fn sign_out(&self) -> Result<(), UserError> { pub async fn sign_out(&self) -> Result<(), UserError> {
let session = self.get_session()?; let session = self.get_session()?;
let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&session.user_id))).execute(&*(self.db_conn()?))?; let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&session.user_id))).execute(&*(self.db_conn()?))?;
@ -106,6 +107,7 @@ impl UserSession {
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(self))]
pub async fn update_user(&self, params: UpdateUserParams) -> Result<(), UserError> { pub async fn update_user(&self, params: UpdateUserParams) -> Result<(), UserError> {
let session = self.get_session()?; let session = self.get_session()?;
let changeset = UserTableChangeset::new(params.clone()); let changeset = UserTableChangeset::new(params.clone());
@ -140,7 +142,7 @@ impl UserSession {
async fn read_user_profile_on_server(&self, token: &str) -> Result<(), UserError> { async fn read_user_profile_on_server(&self, token: &str) -> Result<(), UserError> {
let server = self.server.clone(); let server = self.server.clone();
let token = token.to_owned(); let token = token.to_owned();
let _ = spawn(async move { let _ = tokio::spawn(async move {
match server.get_user(&token).await { match server.get_user(&token).await {
Ok(profile) => { Ok(profile) => {
// //
@ -158,7 +160,7 @@ impl UserSession {
async fn update_user_on_server(&self, token: &str, params: UpdateUserParams) -> Result<(), UserError> { async fn update_user_on_server(&self, token: &str, params: UpdateUserParams) -> Result<(), UserError> {
let server = self.server.clone(); let server = self.server.clone();
let token = token.to_owned(); let token = token.to_owned();
let _ = spawn(async move { let _ = tokio::spawn(async move {
match server.update_user(&token, params).await { match server.update_user(&token, params).await {
Ok(_) => {}, Ok(_) => {},
Err(e) => { Err(e) => {
@ -174,7 +176,7 @@ impl UserSession {
async fn sign_out_on_server(&self, token: &str) -> Result<(), UserError> { async fn sign_out_on_server(&self, token: &str) -> Result<(), UserError> {
let server = self.server.clone(); let server = self.server.clone();
let token = token.to_owned(); let token = token.to_owned();
let _ = spawn(async move { let _ = tokio::spawn(async move {
match server.sign_out(&token).await { match server.sign_out(&token).await {
Ok(_) => {}, Ok(_) => {},
Err(e) => log::error!("Sign out failed: {:?}", e), Err(e) => log::error!("Sign out failed: {:?}", e),

View File

@ -7,20 +7,21 @@ const OBSERVABLE_CATEGORY: &'static str = "Workspace";
#[derive(ProtoBuf_Enum, Debug)] #[derive(ProtoBuf_Enum, Debug)]
pub(crate) enum WorkspaceObservable { pub(crate) enum WorkspaceObservable {
Unknown = 0, Unknown = 0,
UserCreateWorkspace = 10, UserCreateWorkspace = 10,
UserDeleteWorkspace = 11, UserDeleteWorkspace = 11,
WorkspaceUpdated = 12, WorkspaceUpdated = 12,
WorkspaceCreateApp = 13, WorkspaceCreateApp = 13,
WorkspaceDeleteApp = 14, WorkspaceDeleteApp = 14,
WorkspaceListUpdated = 15,
AppUpdated = 21, AppUpdated = 21,
AppCreateView = 23, AppCreateView = 23,
AppDeleteView = 24, AppDeleteView = 24,
ViewUpdated = 31, ViewUpdated = 31,
} }
impl std::default::Default for WorkspaceObservable { impl std::default::Default for WorkspaceObservable {
@ -58,11 +59,7 @@ impl ObservableSender {
} }
pub(crate) fn send(self) { pub(crate) fn send(self) {
log::trace!( log::trace!("Workspace observable id: {}, ty: {:?}", self.subject_id, self.ty);
"Workspace observable id: {}, ty: {:?}",
self.subject_id,
self.ty
);
let subject_payload = match self.payload { let subject_payload = match self.payload {
None => None, None => None,
@ -82,9 +79,7 @@ impl ObservableSender {
} }
} }
pub(crate) fn send_observable(id: &str, ty: WorkspaceObservable) { pub(crate) fn send_observable(id: &str, ty: WorkspaceObservable) { ObservableSender::new(id, ty).send(); }
ObservableSender::new(id, ty).send();
}
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn send_observable_with_payload<T>(id: &str, ty: WorkspaceObservable, payload: T) pub(crate) fn send_observable_with_payload<T>(id: &str, ty: WorkspaceObservable, payload: T)

View File

@ -31,6 +31,7 @@ pub enum WorkspaceObservable {
WorkspaceUpdated = 12, WorkspaceUpdated = 12,
WorkspaceCreateApp = 13, WorkspaceCreateApp = 13,
WorkspaceDeleteApp = 14, WorkspaceDeleteApp = 14,
WorkspaceListUpdated = 15,
AppUpdated = 21, AppUpdated = 21,
AppCreateView = 23, AppCreateView = 23,
AppDeleteView = 24, AppDeleteView = 24,
@ -50,6 +51,7 @@ impl ::protobuf::ProtobufEnum for WorkspaceObservable {
12 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceUpdated), 12 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceUpdated),
13 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceCreateApp), 13 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceCreateApp),
14 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceDeleteApp), 14 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceDeleteApp),
15 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceListUpdated),
21 => ::std::option::Option::Some(WorkspaceObservable::AppUpdated), 21 => ::std::option::Option::Some(WorkspaceObservable::AppUpdated),
23 => ::std::option::Option::Some(WorkspaceObservable::AppCreateView), 23 => ::std::option::Option::Some(WorkspaceObservable::AppCreateView),
24 => ::std::option::Option::Some(WorkspaceObservable::AppDeleteView), 24 => ::std::option::Option::Some(WorkspaceObservable::AppDeleteView),
@ -66,6 +68,7 @@ impl ::protobuf::ProtobufEnum for WorkspaceObservable {
WorkspaceObservable::WorkspaceUpdated, WorkspaceObservable::WorkspaceUpdated,
WorkspaceObservable::WorkspaceCreateApp, WorkspaceObservable::WorkspaceCreateApp,
WorkspaceObservable::WorkspaceDeleteApp, WorkspaceObservable::WorkspaceDeleteApp,
WorkspaceObservable::WorkspaceListUpdated,
WorkspaceObservable::AppUpdated, WorkspaceObservable::AppUpdated,
WorkspaceObservable::AppCreateView, WorkspaceObservable::AppCreateView,
WorkspaceObservable::AppDeleteView, WorkspaceObservable::AppDeleteView,
@ -98,35 +101,37 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceObservable {
} }
static file_descriptor_proto_data: &'static [u8] = b"\ static file_descriptor_proto_data: &'static [u8] = b"\
\n\x10observable.proto*\xe1\x01\n\x13WorkspaceObservable\x12\x0b\n\x07Un\ \n\x10observable.proto*\xfb\x01\n\x13WorkspaceObservable\x12\x0b\n\x07Un\
known\x10\0\x12\x17\n\x13UserCreateWorkspace\x10\n\x12\x17\n\x13UserDele\ known\x10\0\x12\x17\n\x13UserCreateWorkspace\x10\n\x12\x17\n\x13UserDele\
teWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x16\n\x12W\ teWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x16\n\x12W\
orkspaceCreateApp\x10\r\x12\x16\n\x12WorkspaceDeleteApp\x10\x0e\x12\x0e\ orkspaceCreateApp\x10\r\x12\x16\n\x12WorkspaceDeleteApp\x10\x0e\x12\x18\
\n\nAppUpdated\x10\x15\x12\x11\n\rAppCreateView\x10\x17\x12\x11\n\rAppDe\ \n\x14WorkspaceListUpdated\x10\x0f\x12\x0e\n\nAppUpdated\x10\x15\x12\x11\
leteView\x10\x18\x12\x0f\n\x0bViewUpdated\x10\x1fJ\xc4\x03\n\x06\x12\x04\ \n\rAppCreateView\x10\x17\x12\x11\n\rAppDeleteView\x10\x18\x12\x0f\n\x0b\
\0\0\r\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\ ViewUpdated\x10\x1fJ\xed\x03\n\x06\x12\x04\0\0\x0e\x01\n\x08\n\x01\x0c\
\r\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x18\n\x0b\n\x04\x05\0\x02\0\ \x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x0e\x01\n\n\n\x03\x05\0\
\x12\x03\x03\x04\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\x0b\n\ \x01\x12\x03\x02\x05\x18\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x10\n\
\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\ \x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\x0b\n\x0c\n\x05\x05\0\x02\0\
\x12\x03\x04\x04\x1d\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\x04\x17\n\ \x02\x12\x03\x03\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x1d\n\
\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\x1a\x1c\n\x0b\n\x04\x05\0\x02\ \x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\x04\x17\n\x0c\n\x05\x05\0\x02\
\x02\x12\x03\x05\x04\x1d\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x05\x04\ \x01\x02\x12\x03\x04\x1a\x1c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x05\x04\
\x17\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x05\x1a\x1c\n\x0b\n\x04\x05\0\ \x1d\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x05\x04\x17\n\x0c\n\x05\x05\0\
\x02\x03\x12\x03\x06\x04\x1a\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x06\ \x02\x02\x02\x12\x03\x05\x1a\x1c\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x06\
\x04\x14\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x17\x19\n\x0b\n\x04\ \x04\x1a\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x06\x04\x14\n\x0c\n\x05\
\x05\0\x02\x04\x12\x03\x07\x04\x1c\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\ \x05\0\x02\x03\x02\x12\x03\x06\x17\x19\n\x0b\n\x04\x05\0\x02\x04\x12\x03\
\x07\x04\x16\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x07\x19\x1b\n\x0b\n\ \x07\x04\x1c\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x07\x04\x16\n\x0c\n\
\x04\x05\0\x02\x05\x12\x03\x08\x04\x1c\n\x0c\n\x05\x05\0\x02\x05\x01\x12\ \x05\x05\0\x02\x04\x02\x12\x03\x07\x19\x1b\n\x0b\n\x04\x05\0\x02\x05\x12\
\x03\x08\x04\x16\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x08\x19\x1b\n\x0b\ \x03\x08\x04\x1c\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x08\x04\x16\n\x0c\
\n\x04\x05\0\x02\x06\x12\x03\t\x04\x14\n\x0c\n\x05\x05\0\x02\x06\x01\x12\ \n\x05\x05\0\x02\x05\x02\x12\x03\x08\x19\x1b\n\x0b\n\x04\x05\0\x02\x06\
\x03\t\x04\x0e\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\t\x11\x13\n\x0b\n\ \x12\x03\t\x04\x1e\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\t\x04\x18\n\x0c\
\x04\x05\0\x02\x07\x12\x03\n\x04\x17\n\x0c\n\x05\x05\0\x02\x07\x01\x12\ \n\x05\x05\0\x02\x06\x02\x12\x03\t\x1b\x1d\n\x0b\n\x04\x05\0\x02\x07\x12\
\x03\n\x04\x11\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\n\x14\x16\n\x0b\n\ \x03\n\x04\x14\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\n\x04\x0e\n\x0c\n\
\x04\x05\0\x02\x08\x12\x03\x0b\x04\x17\n\x0c\n\x05\x05\0\x02\x08\x01\x12\ \x05\x05\0\x02\x07\x02\x12\x03\n\x11\x13\n\x0b\n\x04\x05\0\x02\x08\x12\
\x03\x0b\x04\x11\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0b\x14\x16\n\x0b\ \x03\x0b\x04\x17\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0b\x04\x11\n\x0c\
\n\x04\x05\0\x02\t\x12\x03\x0c\x04\x15\n\x0c\n\x05\x05\0\x02\t\x01\x12\ \n\x05\x05\0\x02\x08\x02\x12\x03\x0b\x14\x16\n\x0b\n\x04\x05\0\x02\t\x12\
\x03\x0c\x04\x0f\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x0c\x12\x14b\x06pro\ \x03\x0c\x04\x17\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x0c\x04\x11\n\x0c\n\
to3\ \x05\x05\0\x02\t\x02\x12\x03\x0c\x14\x16\n\x0b\n\x04\x05\0\x02\n\x12\x03\
\r\x04\x15\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\r\x04\x0f\n\x0c\n\x05\x05\
\0\x02\n\x02\x12\x03\r\x12\x14b\x06proto3\
"; ";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -7,6 +7,7 @@ enum WorkspaceObservable {
WorkspaceUpdated = 12; WorkspaceUpdated = 12;
WorkspaceCreateApp = 13; WorkspaceCreateApp = 13;
WorkspaceDeleteApp = 14; WorkspaceDeleteApp = 14;
WorkspaceListUpdated = 15;
AppUpdated = 21; AppUpdated = 21;
AppCreateView = 23; AppCreateView = 23;
AppDeleteView = 24; AppDeleteView = 24;

View File

@ -1,10 +1,7 @@
pub async fn spawn<F>(f: F) pub fn spawn<F>(f: F)
where where
F: std::future::Future + Send + 'static, F: std::future::Future + Send + 'static,
F::Output: Send + 'static, F::Output: Send + 'static,
{ {
match tokio::spawn(f).await { let _ = tokio::spawn(f);
Ok(_) => {},
Err(e) => log::error!("{:?}", e),
}
} }

View File

@ -82,7 +82,7 @@ impl WorkspaceController {
pub(crate) async fn read_workspaces(&self, params: QueryWorkspaceParams) -> Result<RepeatedWorkspace, WorkspaceError> { pub(crate) async fn read_workspaces(&self, params: QueryWorkspaceParams) -> Result<RepeatedWorkspace, WorkspaceError> {
let user_id = self.user.user_id()?; let user_id = self.user.user_id()?;
let workspace_tables = self.read_workspace_table(params.workspace_id.clone(), user_id)?; let workspace_tables = self.read_workspace_table(params.workspace_id.clone(), user_id.clone())?;
let mut workspaces = vec![]; let mut workspaces = vec![];
for table in workspace_tables { for table in workspace_tables {
let apps = self.read_apps(&table.id).await?; let apps = self.read_apps(&table.id).await?;
@ -91,7 +91,7 @@ impl WorkspaceController {
workspaces.push(workspace); workspaces.push(workspace);
} }
let _ = self.read_workspaces_on_server(params).await?; let _ = self.read_workspaces_on_server(user_id, params).await?;
Ok(RepeatedWorkspace { items: workspaces }) Ok(RepeatedWorkspace { items: workspaces })
} }
@ -183,12 +183,13 @@ impl WorkspaceController {
} }
#[tracing::instrument(skip(self), err)] #[tracing::instrument(skip(self), err)]
async fn read_workspaces_on_server(&self, params: QueryWorkspaceParams) -> Result<(), WorkspaceError> { async fn read_workspaces_on_server(&self, user_id: String, params: QueryWorkspaceParams) -> Result<(), WorkspaceError> {
let (token, server) = self.token_with_server()?; let (token, server) = self.token_with_server()?;
spawn(async move { spawn(async move {
match server.read_workspace(&token, params).await { match server.read_workspace(&token, params).await {
Ok(_workspaces) => { Ok(workspaces) => {
// TODO: notify log::debug!("Workspace list: {:?}", workspaces);
send_observable(&user_id, WorkspaceObservable::UserCreateWorkspace);
}, },
Err(e) => { Err(e) => {
// TODO: retry? // TODO: retry?
@ -196,6 +197,7 @@ impl WorkspaceController {
}, },
} }
}); });
Ok(()) Ok(())
} }
} }