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/welcome/presentation/welcome_screen.dart';
import 'package:app_flowy/welcome/presentation/splash_screen.dart';
import 'package:flutter/material.dart';
class FlowyAppFactory implements AppFactory {
@override
Widget create() {
return const WelcomeScreen();
return const SplashScreen();
}
}

View File

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

View File

@ -14,28 +14,65 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
Stream<SignUpState> mapEventToState(
SignUpEvent event,
) async* {
yield* event.map(
signUpWithUserEmailAndPassword: (e) async* {
yield* _performActionOnSignUp(
state,
);
},
emailChanged: (EmailChanged value) async* {
yield state.copyWith(email: value.email, successOrFail: none());
},
passwordChanged: (PasswordChanged value) async* {
yield state.copyWith(password: value.password, successOrFail: none());
},
);
yield* event.map(signUpWithUserEmailAndPassword: (e) async* {
yield* _performActionOnSignUp();
}, emailChanged: (EmailChanged value) async* {
yield state.copyWith(email: value.email, successOrFail: none());
}, passwordChanged: (PasswordChanged value) async* {
yield state.copyWith(password: value.password, successOrFail: none());
}, repeatPasswordChanged: (RepeatPasswordChanged value) async* {
yield state.copyWith(
repeatedPassword: value.password, successOrFail: none());
});
}
Stream<SignUpState> _performActionOnSignUp(SignUpState state) async* {
yield state.copyWith(isSubmitting: true);
Stream<SignUpState> _performActionOnSignUp() async* {
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(
(userProfile) => state.copyWith(
isSubmitting: false, successOrFail: some(left(userProfile))),
isSubmitting: false,
successOrFail: some(left(userProfile)),
emailError: none(),
passwordError: none(),
repeatPasswordError: none(),
),
(error) => stateFromCode(error),
);
}
@ -65,6 +102,8 @@ abstract class SignUpEvent with _$SignUpEvent {
SignUpWithUserEmailAndPassword;
const factory SignUpEvent.emailChanged(String email) = EmailChanged;
const factory SignUpEvent.passwordChanged(String password) = PasswordChanged;
const factory SignUpEvent.repeatPasswordChanged(String password) =
RepeatPasswordChanged;
}
@freezed
@ -72,8 +111,10 @@ abstract class SignUpState with _$SignUpState {
const factory SignUpState({
String? email,
String? password,
String? repeatedPassword,
required bool isSubmitting,
required Option<String> passwordError,
required Option<String> repeatPasswordError,
required Option<String> emailError,
required Option<Either<UserProfile, UserError>> successOrFail,
}) = _SignUpState;
@ -81,6 +122,7 @@ abstract class SignUpState with _$SignUpState {
factory SignUpState.initial() => SignUpState(
isSubmitting: false,
passwordError: none(),
repeatPasswordError: none(),
emailError: none(),
successOrFail: none(),
);

View File

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

View File

@ -12,7 +12,7 @@ abstract class IAuth {
}
abstract class IAuthRouter {
void showWorkspaceSelectScreen(BuildContext context, UserProfile user);
void showSignUpScreen(BuildContext context);
void showForgetPasswordScreen(BuildContext context);
void pushWelcomeScreen(BuildContext context, UserProfile userProfile);
void pushSignUpScreen(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/presentation/workspace/workspace_select_screen.dart';
import 'package:dartz/dartz.dart';
@ -34,26 +36,20 @@ class AuthImpl extends IAuth {
class AuthRouterImpl extends IAuthRouter {
@override
void showForgetPasswordScreen(BuildContext context) {
void pushForgetPasswordScreen(BuildContext context) {
// TODO: implement showForgetPasswordScreen
}
@override
void showWorkspaceSelectScreen(BuildContext context, UserProfile user) {
Navigator.of(context).push(
PageRoutes.fade(
() => WorkspaceSelectScreen(
repo: UserRepo(user: user),
),
),
);
void pushWelcomeScreen(BuildContext context, UserProfile userProfile) {
getIt<IWelcomeRoute>().pushWelcomeScreen(context, userProfile);
}
@override
void showSignUpScreen(BuildContext context) {
void pushSignUpScreen(BuildContext context) {
Navigator.of(context).push(
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/user/application/sign_in_bloc.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_ui/widget/rounded_button.dart';
import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
@ -38,7 +38,7 @@ class SignInScreen extends StatelessWidget {
void _handleSuccessOrFail(
Either<UserProfile, UserError> result, BuildContext context) {
result.fold(
(user) => router.showWorkspaceSelectScreen(context, user),
(user) => router.pushWelcomeScreen(context, user),
(error) => _showErrorMessage(context, error.msg),
);
}
@ -106,7 +106,7 @@ class SignUpPrompt extends StatelessWidget {
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 12),
),
onPressed: () => router.showSignUpScreen(context),
onPressed: () => router.pushSignUpScreen(context),
child: Text(
'Sign Up',
style: TextStyle(color: theme.main1),
@ -155,7 +155,7 @@ class ForgetPasswordButton extends StatelessWidget {
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 12),
),
onPressed: () => router.showForgetPasswordScreen(context),
onPressed: () => router.pushForgetPasswordScreen(context),
child: Text(
'Forgot Password?',
style: TextStyle(color: theme.main1),
@ -178,6 +178,7 @@ class PasswordTextField extends StatelessWidget {
builder: (context, state) {
return RoundedInputField(
obscureText: true,
fontSize: 14,
obscureIcon: svgWidgetWithName("home/Hide.svg"),
obscureHideIcon: svgWidgetWithName("home/Show.svg"),
hintText: 'Password',
@ -211,6 +212,7 @@ class EmailTextField extends StatelessWidget {
builder: (context, state) {
return RoundedInputField(
hintText: 'Email',
fontSize: 14,
normalBorderColor: theme.shader4,
highlightBorderColor: theme.red,
errorText: context

View File

@ -1,5 +1,6 @@
import 'package:app_flowy/startup/startup.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:flowy_infra/theme.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';
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
Widget build(BuildContext context) {
@ -22,31 +24,23 @@ class SignUpScreen extends StatelessWidget {
child: BlocListener<SignUpBloc, SignUpState>(
listener: (context, state) {
state.successOrFail.fold(
() => null,
(result) => _handleSuccessOrFail(result, context),
() => {},
(result) => _handleSuccessOrFail(context, result),
);
},
child: const Scaffold(
body: SignUpForm(),
),
child: const Scaffold(body: SignUpForm()),
),
);
}
void _handleSuccessOrFail(
Either<UserProfile, UserError> result, BuildContext context) {
BuildContext context, Either<UserProfile, UserError> result) {
result.fold(
(user) => {
// router.showWorkspaceSelectScreen(context, user)
},
(error) => _showErrorMessage(context, error.msg),
);
}
void _showErrorMessage(BuildContext context, String msg) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(msg),
(user) => router.pushWelcomeScreen(context, user),
(error) => ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(error.msg),
),
),
);
}
@ -70,7 +64,7 @@ class SignUpForm extends StatelessWidget {
const VSpace(30),
const EmailTextField(),
const PasswordTextField(),
const PasswordTextField(hintText: "Repeate password"),
const RepeatPasswordTextField(),
const VSpace(30),
const SignUpButton(),
const VSpace(10),
@ -95,17 +89,14 @@ class SignUpPrompt extends StatelessWidget {
final theme = context.watch<AppTheme>();
return Row(
children: [
Text("Already have an account",
style: TextStyle(color: theme.shader3, fontSize: 12)),
Text(
"Already have an account?",
style: TextStyle(color: theme.shader3, fontSize: 12),
),
TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 12),
),
style: TextButton.styleFrom(textStyle: const TextStyle(fontSize: 12)),
onPressed: () => Navigator.pop(context),
child: Text(
'Sign In',
style: TextStyle(color: theme.main1),
),
child: Text('Sign In', style: TextStyle(color: theme.main1)),
),
],
mainAxisAlignment: MainAxisAlignment.center,
@ -136,10 +127,8 @@ class SignUpButton extends StatelessWidget {
}
class PasswordTextField extends StatelessWidget {
final String hintText;
const PasswordTextField({
Key? key,
this.hintText = "Password",
}) : super(key: key);
@override
@ -155,7 +144,7 @@ class PasswordTextField extends StatelessWidget {
obscureHideIcon: svgWidgetWithName("home/Show.svg"),
fontSize: 14,
fontWeight: FontWeight.w500,
hintText: hintText,
hintText: "Password",
normalBorderColor: theme.shader4,
highlightBorderColor: theme.red,
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 {
const EmailTextField({
Key? key,
@ -186,6 +210,7 @@ class EmailTextField extends StatelessWidget {
builder: (context, state) {
return RoundedInputField(
hintText: 'Email',
fontSize: 14,
normalBorderColor: theme.shader4,
highlightBorderColor: theme.red,
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:freezed_annotation/freezed_annotation.dart';
part 'welcome_bloc.freezed.dart';
part 'splash_bloc.freezed.dart';
class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
final IWelcomeAuth authImpl;
WelcomeBloc(this.authImpl) : super(WelcomeState.initial());
class SplashBloc extends Bloc<SplashEvent, SplashState> {
final ISplashAuth authImpl;
SplashBloc(this.authImpl) : super(SplashState.initial());
@override
Stream<WelcomeState> mapEventToState(WelcomeEvent event) async* {
Stream<SplashState> mapEventToState(SplashEvent event) async* {
yield* event.map(
getUser: (val) async* {
final authState = await authImpl.currentUserProfile();
@ -21,17 +21,17 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
}
@freezed
abstract class WelcomeEvent with _$WelcomeEvent {
const factory WelcomeEvent.getUser() = _GetUser;
abstract class SplashEvent with _$SplashEvent {
const factory SplashEvent.getUser() = _GetUser;
}
@freezed
abstract class WelcomeState implements _$WelcomeState {
const factory WelcomeState({
abstract class SplashState implements _$SplashState {
const factory SplashState({
required AuthState auth,
}) = _WelcomeState;
}) = _SplashState;
factory WelcomeState.initial() => const WelcomeState(
factory SplashState.initial() => const SplashState(
auth: AuthState.initial(),
);
}

View File

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

View File

@ -3,11 +3,13 @@ import 'package:flutter/widgets.dart';
import 'auth_state.dart';
abstract class IWelcomeAuth {
abstract class ISplashAuth {
Future<AuthState> currentUserProfile();
}
abstract class IWelcomeRoute {
Widget pushSignInScreen();
Future<void> pushHomeScreen(BuildContext context, UserProfile profile);
void pushSignInScreen(BuildContext context);
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/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/workspace/application/home/home_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 {
static Future<void> resolve(GetIt getIt) async {
getIt.registerFactory<IWelcomeAuth>(() => WelcomeAuthImpl());
getIt.registerFactory<ISplashAuth>(() => WelcomeAuthImpl());
getIt.registerFactory<IWelcomeRoute>(() => WelcomeRoute());
getIt.registerFactory<HomeBloc>(() => HomeBloc());
getIt.registerFactory<HomeWatcherBloc>(() => HomeWatcherBloc());
getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
getIt
.registerFactory<WelcomeBloc>(() => WelcomeBloc(getIt<IWelcomeAuth>()));
getIt.registerFactory<SplashBloc>(() => SplashBloc(getIt<ISplashAuth>()));
}
}

View File

@ -1,29 +1,28 @@
import 'package:app_flowy/startup/startup.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/i_welcome.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/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_ui/widget/route/animation.dart';
import 'package:flowy_sdk/dispatch/dispatch.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/widgets.dart';
export 'package:app_flowy/welcome/domain/i_welcome.dart';
class WelcomeAuthImpl implements IWelcomeAuth {
class WelcomeAuthImpl implements ISplashAuth {
@override
Future<AuthState> currentUserProfile() {
final result = UserEventGetUserProfile().send();
return result.then((result) {
return result.fold(
(UserProfile) {
return AuthState.authenticated(UserProfile);
(userProfile) {
return AuthState.authenticated(userProfile);
},
(userError) {
return AuthState.unauthenticated(userError);
@ -35,39 +34,35 @@ class WelcomeAuthImpl implements IWelcomeAuth {
class WelcomeRoute implements IWelcomeRoute {
@override
Future<void> pushHomeScreen(BuildContext context, UserProfile user) async {
Future<void> pushWelcomeScreen(BuildContext context, UserProfile user) async {
final repo = UserRepo(user: user);
return WorkspaceEventReadCurWorkspace().send().then(
(result) {
return result.fold(
(workspace) =>
_pushToScreen(context, HomeScreen(repo.user, workspace.id)),
(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,
),
);
final screen = WelcomeScreen(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
Widget pushSignInScreen() {
return SignInScreen(router: getIt<IAuthRouter>());
}
void _pushToScreen(BuildContext context, Widget screen) {
void pushSignInScreen(BuildContext context) {
Navigator.push(
context,
PageRoutes.fade(
() => screen, RouteDurations.slow.inMilliseconds * .001));
context,
PageRoutes.fade(() => SignInScreen(router: getIt<IAuthRouter>()),
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/welcome/domain/auth_state.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/welcome/application/welcome_bloc.dart';
import 'package:flowy_infra_ui/widget/route/animation.dart';
import 'package:flowy_infra/flowy_logger.dart';
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:flowy_infra/time/prelude.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
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
Widget build(BuildContext context) {
return BlocProvider(
create: (context) {
return getIt<WelcomeBloc>()..add(const WelcomeEvent.getUser());
},
child: Scaffold(
body: BlocListener<WelcomeBloc, WelcomeState>(
listener: (context, state) {
state.auth.map(
authenticated: (r) => _handleAuthenticated(context, r),
unauthenticated: (r) => _handleUnauthenticated(context, r),
initial: (r) => {},
);
},
child: const Body(),
),
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),
],
),
),
);
},
),
);
}
void _pushToScreen(BuildContext context, Widget screen) {
/// Let the splash view sit for a bit. Mainly for aesthetics and to ensure a smooth intro animation.
Navigator.push(
context,
PageRoutes.fade(
() => screen, RouteDurations.slow.inMilliseconds * .001));
Widget _renderBody(WorkspaceListState state) {
final body = state.successOrFailure.fold(
(_) => _renderList(state.workspaces),
(error) => FlowyErrorPage(error.toString()),
);
return body;
}
void _handleAuthenticated(BuildContext context, Authenticated result) {
getIt<IWelcomeRoute>().pushHomeScreen(context, result.userProfile);
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", ""));
},
),
);
}
void _handleUnauthenticated(BuildContext context, Unauthenticated result) {
Log.error(result.error);
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,
),
);
}
_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 {
const Body({Key? key}) : super(key: key);
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) {
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(),
],
),
return SizedBox(
height: 46,
child: FlowyTextButton(
workspace.name,
fontSize: 14,
onPressed: () => onPressed(workspace),
),
);
}

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() {
_logger = Logger(
printer: PrettyPrinter(
methodCount: 2, // number of method calls to be displayed
methodCount: 0, // number of method calls to be displayed
errorMethodCount:
8, // number of method calls if stacktrace is provided
lineLength: 120, // width of the output

View File

@ -85,13 +85,18 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
];
if (widget.errorText.isNotEmpty) {
children.add(Text(
widget.errorText,
style: TextStyle(
color: widget.highlightBorderColor,
fontWeight: widget.fontWeight,
fontSize: widget.fontSize),
));
children.add(
Align(
alignment: Alignment.centerLeft,
child: Text(
widget.errorText,
style: TextStyle(
color: widget.highlightBorderColor,
fontWeight: widget.fontWeight,
fontSize: widget.fontSize),
),
),
);
}
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 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 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 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');
@ -28,6 +29,7 @@ class WorkspaceObservable extends $pb.ProtobufEnum {
WorkspaceUpdated,
WorkspaceCreateApp,
WorkspaceDeleteApp,
WorkspaceListUpdated,
AppUpdated,
AppCreateView,
AppDeleteView,

View File

@ -18,6 +18,7 @@ const WorkspaceObservable$json = const {
const {'1': 'WorkspaceUpdated', '2': 12},
const {'1': 'WorkspaceCreateApp', '2': 13},
const {'1': 'WorkspaceDeleteApp', '2': 14},
const {'1': 'WorkspaceListUpdated', '2': 15},
const {'1': 'AppUpdated', '2': 21},
const {'1': 'AppCreateView', '2': 23},
const {'1': 'AppDeleteView', '2': 24},
@ -26,4 +27,4 @@ const WorkspaceObservable$json = const {
};
/// 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) {
// https://stackoverflow.com/questions/36502401/postgres-drop-database-error-pq-cannot-drop-the-currently-open-database?rq=1
let configuration = {
let mut c = get_configuration().expect("Failed to read configuration.");
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 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)));
return 1;

View File

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

View File

@ -85,7 +85,7 @@ impl UpdateUserRequest {
}
}
#[derive(ProtoBuf, Default, Clone)]
#[derive(ProtoBuf, Default, Clone, Debug)]
pub struct UpdateUserParams {
// TODO: remove user id
#[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\
\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\
\x07Expired\x10\x02J\xbb\x08\n\x06\x12\x04\0\0\x19\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\
\x01\x12\x03\x01\x08\x11\n\x0b\n\x04\x04\0\x02\0\x12\x03\x02\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\
\x12\x03\x02\x0b\x10\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x02\x13\x14\n\n\
\n\x02\x04\x01\x12\x04\x04\0\x08\x01\n\n\n\x03\x04\x01\x01\x12\x03\x04\
\x08\x13\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x05\x04\x12\n\x0c\n\x05\x04\
\x01\x02\0\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\
\x05\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x05\x10\x11\n\x0b\n\x04\
\x04\x01\x02\x01\x12\x03\x06\x04\x15\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\
\x03\x06\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x06\x0b\x10\n\x0c\
\n\x05\x04\x01\x02\x01\x03\x12\x03\x06\x13\x14\n\x0b\n\x04\x04\x01\x02\
\x02\x12\x03\x07\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x07\x04\
\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x07\x0b\x0f\n\x0c\n\x05\x04\
\x01\x02\x02\x03\x12\x03\x07\x12\x13\n\n\n\x02\x04\x02\x12\x04\t\0\x0e\
\x01\n\n\n\x03\x04\x02\x01\x12\x03\t\x08\x19\n\x0b\n\x04\x04\x02\x02\0\
\x12\x03\n\x04\x12\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\
\x05\x04\x02\x02\0\x01\x12\x03\n\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\
\x04\x02\x08\0\x01\x12\x03\x0b\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\
\x05\x04\x02\x02\x01\x01\x12\x03\x0b\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\
\x05\x04\x02\x08\x01\x01\x12\x03\x0c\n\x16\n\x0b\n\x04\x04\x02\x02\x02\
\x12\x03\x0c\x19*\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\x0c\x19\x1f\n\
\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x0c\x20%\n\x0c\n\x05\x04\x02\x02\
\x02\x03\x12\x03\x0c()\n\x0b\n\x04\x04\x02\x08\x02\x12\x03\r\x042\n\x0c\
\n\x05\x04\x02\x08\x02\x01\x12\x03\r\n\x19\n\x0b\n\x04\x04\x02\x02\x03\
\x12\x03\r\x1c0\n\x0c\n\x05\x04\x02\x02\x03\x05\x12\x03\r\x1c\"\n\x0c\n\
\x05\x04\x02\x02\x03\x01\x12\x03\r#+\n\x0c\n\x05\x04\x02\x02\x03\x03\x12\
\x03\r./\n\n\n\x02\x04\x03\x12\x04\x0f\0\x14\x01\n\n\n\x03\x04\x03\x01\
\x12\x03\x0f\x08\x18\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x10\x04\x12\n\x0c\
\n\x05\x04\x03\x02\0\x05\x12\x03\x10\x04\n\n\x0c\n\x05\x04\x03\x02\0\x01\
\x12\x03\x10\x0b\r\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x10\x10\x11\n\
\x0b\n\x04\x04\x03\x08\0\x12\x03\x11\x04*\n\x0c\n\x05\x04\x03\x08\0\x01\
\x12\x03\x11\n\x15\n\x0b\n\x04\x04\x03\x02\x01\x12\x03\x11\x18(\n\x0c\n\
\x05\x04\x03\x02\x01\x05\x12\x03\x11\x18\x1e\n\x0c\n\x05\x04\x03\x02\x01\
\x01\x12\x03\x11\x1f#\n\x0c\n\x05\x04\x03\x02\x01\x03\x12\x03\x11&'\n\
\x0b\n\x04\x04\x03\x08\x01\x12\x03\x12\x04,\n\x0c\n\x05\x04\x03\x08\x01\
\x01\x12\x03\x12\n\x16\n\x0b\n\x04\x04\x03\x02\x02\x12\x03\x12\x19*\n\
\x0c\n\x05\x04\x03\x02\x02\x05\x12\x03\x12\x19\x1f\n\x0c\n\x05\x04\x03\
\x02\x02\x01\x12\x03\x12\x20%\n\x0c\n\x05\x04\x03\x02\x02\x03\x12\x03\
\x12()\n\x0b\n\x04\x04\x03\x08\x02\x12\x03\x13\x042\n\x0c\n\x05\x04\x03\
\x08\x02\x01\x12\x03\x13\n\x19\n\x0b\n\x04\x04\x03\x02\x03\x12\x03\x13\
\x1c0\n\x0c\n\x05\x04\x03\x02\x03\x05\x12\x03\x13\x1c\"\n\x0c\n\x05\x04\
\x03\x02\x03\x01\x12\x03\x13#+\n\x0c\n\x05\x04\x03\x02\x03\x03\x12\x03\
\x13./\n\n\n\x02\x05\0\x12\x04\x15\0\x19\x01\n\n\n\x03\x05\0\x01\x12\x03\
\x15\x05\x0f\n\x0b\n\x04\x05\0\x02\0\x12\x03\x16\x04\x10\n\x0c\n\x05\x05\
\0\x02\0\x01\x12\x03\x16\x04\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x16\
\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x17\x04\x0e\n\x0c\n\x05\x05\0\
\x02\x01\x01\x12\x03\x17\x04\t\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x17\
\x0c\r\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x18\x04\x10\n\x0c\n\x05\x05\0\
\x02\x02\x01\x12\x03\x18\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\
\x18\x0e\x0fb\x06proto3\
\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\x02\0\x04\x01\n\n\n\x03\x04\0\
\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\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\
\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\x05\0\t\x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\x08\
\x13\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x06\x04\x12\n\x0c\n\x05\x04\x01\
\x02\0\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x06\
\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x06\x10\x11\n\x0b\n\x04\x04\
\x01\x02\x01\x12\x03\x07\x04\x15\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\
\x07\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x07\x0b\x10\n\x0c\n\
\x05\x04\x01\x02\x01\x03\x12\x03\x07\x13\x14\n\x0b\n\x04\x04\x01\x02\x02\
\x12\x03\x08\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x08\x04\n\n\
\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x08\x0b\x0f\n\x0c\n\x05\x04\x01\
\x02\x02\x03\x12\x03\x08\x12\x13\n\n\n\x02\x04\x02\x12\x04\n\0\x0f\x01\n\
\n\n\x03\x04\x02\x01\x12\x03\n\x08\x19\n\x0b\n\x04\x04\x02\x02\0\x12\x03\
\x0b\x04\x12\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0b\x04\n\n\x0c\n\x05\
\x04\x02\x02\0\x01\x12\x03\x0b\x0b\r\n\x0c\n\x05\x04\x02\x02\0\x03\x12\
\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\x0c\n\x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\
\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\x0c\x1f#\n\x0c\n\x05\x04\x02\x02\x01\
\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\r\n\x16\n\x0b\n\x04\x04\x02\x02\x02\x12\
\x03\r\x19*\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\r\x19\x1f\n\x0c\n\
\x05\x04\x02\x02\x02\x01\x12\x03\r\x20%\n\x0c\n\x05\x04\x02\x02\x02\x03\
\x12\x03\r()\n\x0b\n\x04\x04\x02\x08\x02\x12\x03\x0e\x042\n\x0c\n\x05\
\x04\x02\x08\x02\x01\x12\x03\x0e\n\x19\n\x0b\n\x04\x04\x02\x02\x03\x12\
\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\x0e#+\n\x0c\n\x05\x04\x02\x02\x03\x03\
\x12\x03\x0e./\n\n\n\x02\x04\x03\x12\x04\x10\0\x15\x01\n\n\n\x03\x04\x03\
\x01\x12\x03\x10\x08\x18\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x11\x04\x12\n\
\x0c\n\x05\x04\x03\x02\0\x05\x12\x03\x11\x04\n\n\x0c\n\x05\x04\x03\x02\0\
\x01\x12\x03\x11\x0b\r\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x11\x10\x11\
\n\x0b\n\x04\x04\x03\x08\0\x12\x03\x12\x04*\n\x0c\n\x05\x04\x03\x08\0\
\x01\x12\x03\x12\n\x15\n\x0b\n\x04\x04\x03\x02\x01\x12\x03\x12\x18(\n\
\x0c\n\x05\x04\x03\x02\x01\x05\x12\x03\x12\x18\x1e\n\x0c\n\x05\x04\x03\
\x02\x01\x01\x12\x03\x12\x1f#\n\x0c\n\x05\x04\x03\x02\x01\x03\x12\x03\
\x12&'\n\x0b\n\x04\x04\x03\x08\x01\x12\x03\x13\x04,\n\x0c\n\x05\x04\x03\
\x08\x01\x01\x12\x03\x13\n\x16\n\x0b\n\x04\x04\x03\x02\x02\x12\x03\x13\
\x19*\n\x0c\n\x05\x04\x03\x02\x02\x05\x12\x03\x13\x19\x1f\n\x0c\n\x05\
\x04\x03\x02\x02\x01\x12\x03\x13\x20%\n\x0c\n\x05\x04\x03\x02\x02\x03\
\x12\x03\x13()\n\x0b\n\x04\x04\x03\x08\x02\x12\x03\x14\x042\n\x0c\n\x05\
\x04\x03\x08\x02\x01\x12\x03\x14\n\x19\n\x0b\n\x04\x04\x03\x02\x03\x12\
\x03\x14\x1c0\n\x0c\n\x05\x04\x03\x02\x03\x05\x12\x03\x14\x1c\"\n\x0c\n\
\x05\x04\x03\x02\x03\x01\x12\x03\x14#+\n\x0c\n\x05\x04\x03\x02\x03\x03\
\x12\x03\x14./\n\n\n\x02\x05\0\x12\x04\x16\0\x1a\x01\n\n\n\x03\x05\0\x01\
\x12\x03\x16\x05\x0f\n\x0b\n\x04\x05\0\x02\0\x12\x03\x17\x04\x10\n\x0c\n\
\x05\x05\0\x02\0\x01\x12\x03\x17\x04\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\
\x03\x17\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x18\x04\x0e\n\x0c\n\
\x05\x05\0\x02\x01\x01\x12\x03\x18\x04\t\n\x0c\n\x05\x05\0\x02\x01\x02\
\x12\x03\x18\x0c\r\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x19\x04\x10\n\x0c\n\
\x05\x05\0\x02\x02\x01\x12\x03\x19\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\
\x12\x03\x19\x0e\x0fb\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -1,4 +1,5 @@
syntax = "proto3";
message UserToken {
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;
pub mod user;

View File

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

View File

@ -7,20 +7,21 @@ const OBSERVABLE_CATEGORY: &'static str = "Workspace";
#[derive(ProtoBuf_Enum, Debug)]
pub(crate) enum WorkspaceObservable {
Unknown = 0,
Unknown = 0,
UserCreateWorkspace = 10,
UserDeleteWorkspace = 11,
UserCreateWorkspace = 10,
UserDeleteWorkspace = 11,
WorkspaceUpdated = 12,
WorkspaceCreateApp = 13,
WorkspaceDeleteApp = 14,
WorkspaceUpdated = 12,
WorkspaceCreateApp = 13,
WorkspaceDeleteApp = 14,
WorkspaceListUpdated = 15,
AppUpdated = 21,
AppCreateView = 23,
AppDeleteView = 24,
AppUpdated = 21,
AppCreateView = 23,
AppDeleteView = 24,
ViewUpdated = 31,
ViewUpdated = 31,
}
impl std::default::Default for WorkspaceObservable {
@ -58,11 +59,7 @@ impl ObservableSender {
}
pub(crate) fn send(self) {
log::trace!(
"Workspace observable id: {}, ty: {:?}",
self.subject_id,
self.ty
);
log::trace!("Workspace observable id: {}, ty: {:?}", self.subject_id, self.ty);
let subject_payload = match self.payload {
None => None,
@ -82,9 +79,7 @@ impl ObservableSender {
}
}
pub(crate) fn send_observable(id: &str, ty: WorkspaceObservable) {
ObservableSender::new(id, ty).send();
}
pub(crate) fn send_observable(id: &str, ty: WorkspaceObservable) { ObservableSender::new(id, ty).send(); }
#[allow(dead_code)]
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,
WorkspaceCreateApp = 13,
WorkspaceDeleteApp = 14,
WorkspaceListUpdated = 15,
AppUpdated = 21,
AppCreateView = 23,
AppDeleteView = 24,
@ -50,6 +51,7 @@ impl ::protobuf::ProtobufEnum for WorkspaceObservable {
12 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceUpdated),
13 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceCreateApp),
14 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceDeleteApp),
15 => ::std::option::Option::Some(WorkspaceObservable::WorkspaceListUpdated),
21 => ::std::option::Option::Some(WorkspaceObservable::AppUpdated),
23 => ::std::option::Option::Some(WorkspaceObservable::AppCreateView),
24 => ::std::option::Option::Some(WorkspaceObservable::AppDeleteView),
@ -66,6 +68,7 @@ impl ::protobuf::ProtobufEnum for WorkspaceObservable {
WorkspaceObservable::WorkspaceUpdated,
WorkspaceObservable::WorkspaceCreateApp,
WorkspaceObservable::WorkspaceDeleteApp,
WorkspaceObservable::WorkspaceListUpdated,
WorkspaceObservable::AppUpdated,
WorkspaceObservable::AppCreateView,
WorkspaceObservable::AppDeleteView,
@ -98,35 +101,37 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceObservable {
}
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\
teWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x16\n\x12W\
orkspaceCreateApp\x10\r\x12\x16\n\x12WorkspaceDeleteApp\x10\x0e\x12\x0e\
\n\nAppUpdated\x10\x15\x12\x11\n\rAppCreateView\x10\x17\x12\x11\n\rAppDe\
leteView\x10\x18\x12\x0f\n\x0bViewUpdated\x10\x1fJ\xc4\x03\n\x06\x12\x04\
\0\0\r\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\
\r\x01\n\n\n\x03\x05\0\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\x01\x12\x03\x03\x04\x0b\n\
\x0c\n\x05\x05\0\x02\0\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\x01\x12\x03\x04\x04\x17\n\
\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\x1a\x1c\n\x0b\n\x04\x05\0\x02\
\x02\x12\x03\x05\x04\x1d\n\x0c\n\x05\x05\0\x02\x02\x01\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\
\x02\x03\x12\x03\x06\x04\x1a\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x06\
\x04\x14\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x17\x19\n\x0b\n\x04\
\x05\0\x02\x04\x12\x03\x07\x04\x1c\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\
\x07\x04\x16\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x07\x19\x1b\n\x0b\n\
\x04\x05\0\x02\x05\x12\x03\x08\x04\x1c\n\x0c\n\x05\x05\0\x02\x05\x01\x12\
\x03\x08\x04\x16\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x08\x19\x1b\n\x0b\
\n\x04\x05\0\x02\x06\x12\x03\t\x04\x14\n\x0c\n\x05\x05\0\x02\x06\x01\x12\
\x03\t\x04\x0e\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\t\x11\x13\n\x0b\n\
\x04\x05\0\x02\x07\x12\x03\n\x04\x17\n\x0c\n\x05\x05\0\x02\x07\x01\x12\
\x03\n\x04\x11\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\n\x14\x16\n\x0b\n\
\x04\x05\0\x02\x08\x12\x03\x0b\x04\x17\n\x0c\n\x05\x05\0\x02\x08\x01\x12\
\x03\x0b\x04\x11\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0b\x14\x16\n\x0b\
\n\x04\x05\0\x02\t\x12\x03\x0c\x04\x15\n\x0c\n\x05\x05\0\x02\t\x01\x12\
\x03\x0c\x04\x0f\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x0c\x12\x14b\x06pro\
to3\
orkspaceCreateApp\x10\r\x12\x16\n\x12WorkspaceDeleteApp\x10\x0e\x12\x18\
\n\x14WorkspaceListUpdated\x10\x0f\x12\x0e\n\nAppUpdated\x10\x15\x12\x11\
\n\rAppCreateView\x10\x17\x12\x11\n\rAppDeleteView\x10\x18\x12\x0f\n\x0b\
ViewUpdated\x10\x1fJ\xed\x03\n\x06\x12\x04\0\0\x0e\x01\n\x08\n\x01\x0c\
\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x0e\x01\n\n\n\x03\x05\0\
\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\x01\x12\x03\x03\x04\x0b\n\x0c\n\x05\x05\0\x02\0\
\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\x01\x12\x03\x04\x04\x17\n\x0c\n\x05\x05\0\x02\
\x01\x02\x12\x03\x04\x1a\x1c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x05\x04\
\x1d\n\x0c\n\x05\x05\0\x02\x02\x01\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\x02\x03\x12\x03\x06\
\x04\x1a\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x06\x04\x14\n\x0c\n\x05\
\x05\0\x02\x03\x02\x12\x03\x06\x17\x19\n\x0b\n\x04\x05\0\x02\x04\x12\x03\
\x07\x04\x1c\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x07\x04\x16\n\x0c\n\
\x05\x05\0\x02\x04\x02\x12\x03\x07\x19\x1b\n\x0b\n\x04\x05\0\x02\x05\x12\
\x03\x08\x04\x1c\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x08\x04\x16\n\x0c\
\n\x05\x05\0\x02\x05\x02\x12\x03\x08\x19\x1b\n\x0b\n\x04\x05\0\x02\x06\
\x12\x03\t\x04\x1e\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\t\x04\x18\n\x0c\
\n\x05\x05\0\x02\x06\x02\x12\x03\t\x1b\x1d\n\x0b\n\x04\x05\0\x02\x07\x12\
\x03\n\x04\x14\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\n\x04\x0e\n\x0c\n\
\x05\x05\0\x02\x07\x02\x12\x03\n\x11\x13\n\x0b\n\x04\x05\0\x02\x08\x12\
\x03\x0b\x04\x17\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0b\x04\x11\n\x0c\
\n\x05\x05\0\x02\x08\x02\x12\x03\x0b\x14\x16\n\x0b\n\x04\x05\0\x02\t\x12\
\x03\x0c\x04\x17\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x0c\x04\x11\n\x0c\n\
\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;

View File

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

View File

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

View File

@ -82,7 +82,7 @@ impl WorkspaceController {
pub(crate) async fn read_workspaces(&self, params: QueryWorkspaceParams) -> Result<RepeatedWorkspace, WorkspaceError> {
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![];
for table in workspace_tables {
let apps = self.read_apps(&table.id).await?;
@ -91,7 +91,7 @@ impl WorkspaceController {
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 })
}
@ -183,12 +183,13 @@ impl WorkspaceController {
}
#[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()?;
spawn(async move {
match server.read_workspace(&token, params).await {
Ok(_workspaces) => {
// TODO: notify
Ok(workspaces) => {
log::debug!("Workspace list: {:?}", workspaces);
send_observable(&user_id, WorkspaceObservable::UserCreateWorkspace);
},
Err(e) => {
// TODO: retry?
@ -196,6 +197,7 @@ impl WorkspaceController {
},
}
});
Ok(())
}
}