feat: support canceling the sign-in event (#4342)

This commit is contained in:
Lucas.Xu 2024-01-09 16:09:44 +07:00 committed by GitHub
parent dcb070909c
commit db2e23172a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 130 additions and 95 deletions

View File

@ -2,13 +2,13 @@ import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart';
import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:dartz/dartz.dart';
import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
show UserProfilePB;
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'sign_in_bloc.freezed.dart';
@ -105,6 +105,16 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
}
}
},
cancel: (value) {
emit(
state.copyWith(
isSubmitting: false,
emailError: none(),
passwordError: none(),
successOrFail: none(),
),
);
},
);
});
}
@ -245,6 +255,7 @@ class SignInEvent with _$SignInEvent {
const factory SignInEvent.passwordChanged(String password) = PasswordChanged;
const factory SignInEvent.deepLinkStateChange(DeepLinkResult result) =
_DeepLinkStateChange;
const factory SignInEvent.cancel() = _Cancel;
}
@freezed

View File

@ -0,0 +1,39 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/base/app_bar_actions.dart';
import 'package:appflowy/user/application/sign_in_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class MobileLoadingScreen extends StatelessWidget {
const MobileLoadingScreen({
super.key,
});
@override
Widget build(BuildContext context) {
const double spacing = 16;
return Scaffold(
appBar: AppBar(
leading: AppBarCloseButton(
onTap: () => context.read<SignInBloc>().add(
const SignInEvent.cancel(),
),
),
elevation: 0,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlowyText(LocaleKeys.signIn_signingInText.tr()),
const VSpace(spacing),
const CircularProgressIndicator(),
],
),
),
);
}
}

View File

@ -2,106 +2,89 @@ import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class MobileSignInScreen extends StatelessWidget {
const MobileSignInScreen({super.key, required this.isLoading});
final bool isLoading;
const MobileSignInScreen({
super.key,
});
@override
Widget build(BuildContext context) {
const double spacing = 16;
// Welcome to Appflowy
final welcomeString = LocaleKeys.welcomeText.tr();
final style = Theme.of(context);
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
resizeToAvoidBottomInset: false,
body: isLoading
? // TODO(yijing): improve loading effect in the future
const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Signing in...'),
VSpace(spacing),
CircularProgressIndicator(),
],
),
)
: Padding(
padding: const EdgeInsets.fromLTRB(50, 0, 50, 30),
child: Column(
children: [
const Spacer(
flex: 4,
),
const FlowySvg(
FlowySvgs.flowy_logo_xl,
size: Size.square(64),
blendMode: null,
),
const VSpace(spacing * 2),
// Welcome to
Text(
welcomeString.substring(0, welcomeString.length - 8),
style: style.textTheme.displayMedium,
textAlign: TextAlign.center,
),
// Appflowy
Text(
welcomeString.substring(welcomeString.length - 8),
style: style.textTheme.displayLarge,
textAlign: TextAlign.center,
),
const VSpace(spacing),
// TODO(yijing): confirm the subtitle before release app
Text(
'You are in charge of your data and customizations.',
style: style.textTheme.bodyMedium?.copyWith(
color: style.colorScheme.onSecondary,
),
textAlign: TextAlign.center,
),
const Spacer(
flex: 2,
),
if (!PlatformExtension.isMobile) ...[
const SignInAnonymousButton(),
const VSpace(spacing),
],
if (isAuthEnabled) ...[
if (!PlatformExtension.isMobile) ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Expanded(child: Divider()),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(
LocaleKeys.signIn_or.tr(),
style: style.textTheme.bodyMedium?.copyWith(
color: style.colorScheme.onSecondary,
),
),
),
const Expanded(child: Divider()),
],
),
const VSpace(spacing),
],
const ThirdPartySignInButtons(),
],
if (!isAuthEnabled)
const Spacer(
flex: 2,
),
const VSpace(spacing),
],
),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 50, horizontal: 40),
child: Column(
children: [
const Spacer(
flex: 4,
),
const FlowySvg(
FlowySvgs.flowy_logo_xl,
size: Size.square(64),
blendMode: null,
),
const VSpace(spacing * 2),
// Welcome to
FlowyText(
LocaleKeys.welcomeTo.tr(),
textAlign: TextAlign.center,
fontSize: 32,
fontWeight: FontWeight.w700,
),
// AppFlowy
FlowyText(
LocaleKeys.appName.tr(),
textAlign: TextAlign.center,
fontSize: 32,
color: const Color(0xFF00BCF0),
fontWeight: FontWeight.w700,
),
const VSpace(spacing),
const Spacer(
flex: 2,
),
// disable anonymous sign in release mode.
if (kDebugMode) ...[
const SignInAnonymousButton(),
const VSpace(spacing),
],
// if the cloud env is enabled, show the third-party sign in buttons.
if (isAuthEnabled) ...[
if (kDebugMode) ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Expanded(child: Divider()),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: FlowyText(
LocaleKeys.signIn_or.tr(),
color: colorScheme.onSecondary,
),
),
const Expanded(child: Divider()),
],
),
const VSpace(spacing),
],
const ThirdPartySignInButtons(),
],
if (!isAuthEnabled)
const Spacer(
flex: 2,
),
const VSpace(spacing),
],
),
),
);
}
}

View File

@ -2,6 +2,7 @@ import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/sign_in_bloc.dart';
import 'package:appflowy/user/presentation/router.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/desktop_sign_in_screen.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/mobile_loading_screen.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/mobile_sign_in_screen.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
@ -32,12 +33,11 @@ class SignInScreen extends StatelessWidget {
);
},
builder: (context, state) {
// When user is logining through 3rd party, a loading widget will appear on the screen. [isLoading] is used to control it is on or not.
final isLoading = context.read<SignInBloc>().state.isSubmitting;
if (PlatformExtension.isMobile) {
return MobileSignInScreen(
isLoading: isLoading,
);
return isLoading
? const MobileLoadingScreen()
: const MobileSignInScreen();
}
return DesktopSignInScreen(
isLoading: isLoading,

View File

@ -2,6 +2,7 @@
"appName": "AppFlowy",
"defaultUsername": "Me",
"welcomeText": "Welcome to @:appName",
"welcomeTo": "Welcome to",
"githubStarText": "Star on GitHub",
"subscribeNewsletterText": "Subscribe to Newsletter",
"letsGoButtonText": "Quick Start",
@ -35,6 +36,7 @@
"loginStartWithAnonymous": "Start with an anonymous session",
"continueAnonymousUser": "Continue with an anonymous session",
"buttonText": "Sign In",
"signingInText": "Signing in...",
"forgotPassword": "Forgot Password?",
"emailHint": "Email",
"passwordHint": "Password",