feat: enable anonymous sign in on mobile (#4442)

* feat: enable anoymous login on mobile

* feat: support signin with third party serices
This commit is contained in:
Lucas.Xu 2024-01-22 22:36:16 +08:00 committed by GitHub
parent 2cdee386c2
commit 38902ed599
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 182 additions and 111 deletions

View File

@ -1,12 +1,15 @@
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/env/env.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/setting/cloud/cloud_setting_group.dart';
import 'package:appflowy/mobile/presentation/presentation.dart';
import 'package:appflowy/mobile/presentation/setting/logout_setting_group.dart';
import 'package:appflowy/mobile/presentation/setting/cloud/cloud_setting_group.dart';
import 'package:appflowy/mobile/presentation/setting/user_session_setting_group.dart';
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
class MobileHomeSettingPage extends StatefulWidget {
@ -30,6 +33,7 @@ class _MobileHomeSettingPageState extends State<MobileHomeSettingPage> {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator.adaptive());
}
final userProfile = snapshot.data?.fold((error) {
errorMsg = error.msg;
return null;
@ -42,36 +46,48 @@ class _MobileHomeSettingPageState extends State<MobileHomeSettingPage> {
title: Text(LocaleKeys.settings_title.tr()),
),
body: userProfile == null
? FlowyMobileStateContainer.error(
emoji: '🛸',
title: LocaleKeys.settings_mobile_userprofileError.tr(),
description: LocaleKeys
.settings_mobile_userprofileErrorDescription
.tr(),
errorMsg: errorMsg,
)
: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
PersonalInfoSettingGroup(
userProfile: userProfile,
),
// TODO(yijing): implement this along with Notification Page
const NotificationsSettingGroup(),
const AppearanceSettingGroup(),
const LanguageSettingGroup(),
if (Env.enableCustomCloud) const CloudSettingGroup(),
const SupportSettingGroup(),
const AboutSettingGroup(),
const LogoutSettingGroup(),
],
),
),
),
? _buildErrorWidget(errorMsg)
: _buildSettingsWidget(userProfile),
);
}),
);
}
Widget _buildErrorWidget(String? errorMsg) {
return FlowyMobileStateContainer.error(
emoji: '🛸',
title: LocaleKeys.settings_mobile_userprofileError.tr(),
description: LocaleKeys.settings_mobile_userprofileErrorDescription.tr(),
errorMsg: errorMsg,
);
}
Widget _buildSettingsWidget(UserProfilePB userProfile) {
// show the third-party sign in buttons if user logged in with local session and auth is enabled.
final showThirdPartyLogin =
userProfile.authenticator == AuthenticatorPB.Local && isAuthEnabled;
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
PersonalInfoSettingGroup(
userProfile: userProfile,
),
const NotificationsSettingGroup(),
const AppearanceSettingGroup(),
const LanguageSettingGroup(),
if (Env.enableCustomCloud) const CloudSettingGroup(),
const SupportSettingGroup(),
const AboutSettingGroup(),
UserSessionSettingGroup(
showThirdPartyLogin: showThirdPartyLogin,
),
const VSpace(20),
],
),
),
);
}
}

View File

@ -39,7 +39,7 @@ class AboutSettingGroup extends StatelessWidget {
),
),
],
showDivider: false,
showDivider: true,
);
}
}

View File

@ -0,0 +1,54 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy/user/application/sign_in_bloc.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/sign_in_or_logout_button.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.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 UserSessionSettingGroup extends StatelessWidget {
const UserSessionSettingGroup({
super.key,
required this.showThirdPartyLogin,
});
final bool showThirdPartyLogin;
@override
Widget build(BuildContext context) {
return Column(
children: [
if (showThirdPartyLogin) ...[
BlocProvider(
create: (context) => getIt<SignInBloc>(),
child: BlocConsumer<SignInBloc, SignInState>(
listener: (context, state) {
state.successOrFail.fold(
() => null,
(result) => result.fold(
(l) {},
(r) async => await runAppFlowy(),
),
);
},
builder: (context, state) {
return const ThirdPartySignInButtons();
},
),
),
const VSpace(8),
],
MobileSignInOrLogoutButton(
labelText: LocaleKeys.settings_menu_logout.tr(),
onPressed: () async {
await getIt<AuthService>().signOut();
runAppFlowy();
},
),
],
);
}
}

View File

@ -4,7 +4,6 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.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 {
@ -50,31 +49,26 @@ class MobileSignInScreen extends StatelessWidget {
flex: 2,
),
// disable anonymous sign in release mode.
if (kDebugMode) ...[
const SignInAnonymousButton(),
const VSpace(spacing),
],
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,
),
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 Expanded(child: Divider()),
],
),
const VSpace(spacing),
const ThirdPartySignInButtons(),
],
if (!isAuthEnabled)

View File

@ -0,0 +1,63 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
class MobileSignInOrLogoutButton extends StatelessWidget {
const MobileSignInOrLogoutButton({
super.key,
this.icon,
required this.labelText,
required this.onPressed,
});
final FlowySvgData? icon;
final String labelText;
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
final style = Theme.of(context);
return GestureDetector(
onTap: onPressed,
child: Container(
height: 48,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(4),
),
border: Border.all(
color: style.colorScheme.outline,
width: 0.5,
),
),
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (icon != null) ...[
SizedBox(
// The icon could be in different height as original aspect ratio, we use a fixed sizebox to wrap it to make sure they all occupy the same space.
width: 30,
height: 30,
child: Center(
child: SizedBox(
width: 24,
child: FlowySvg(
icon!,
blendMode: null,
),
),
),
),
const HSpace(8),
],
Text(
labelText,
style: Theme.of(context).textTheme.titleSmall,
),
],
),
),
);
}
}

View File

@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/user/application/sign_in_bloc.dart';
import 'package:appflowy/user/presentation/presentation.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/sign_in_or_logout_button.dart';
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart';
@ -80,7 +81,7 @@ class _ThirdPartySignInButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (PlatformExtension.isMobile) {
return _MobileSignInButton(
return MobileSignInOrLogoutButton(
icon: icon,
labelText: labelText,
onPressed: onPressed,
@ -162,63 +163,6 @@ class _DesktopSignInButton extends StatelessWidget {
}
}
class _MobileSignInButton extends StatelessWidget {
const _MobileSignInButton({
required this.icon,
required this.labelText,
required this.onPressed,
});
final FlowySvgData icon;
final String labelText;
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
final style = Theme.of(context);
return GestureDetector(
onTap: onPressed,
child: Container(
height: 48,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(4),
),
border: Border.all(
color: style.colorScheme.outline,
width: 0.5,
),
),
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
// The icon could be in different height as original aspect ratio, we use a fixed sizebox to wrap it to make sure they all occupy the same space.
width: 30,
height: 30,
child: Center(
child: SizedBox(
width: 24,
child: FlowySvg(
icon,
blendMode: null,
),
),
),
),
const HSpace(8),
Text(
labelText,
style: Theme.of(context).textTheme.titleSmall,
),
],
),
),
);
}
}
void _signInWithGoogle(BuildContext context) {
context.read<SignInBloc>().add(
const SignInEvent.signedInWithOAuth('google'),