|
@@ -4,6 +4,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
|
import 'package:appflowy/startup/startup.dart';
|
|
import 'package:appflowy/startup/startup.dart';
|
|
import 'package:appflowy/user/application/sign_in_bloc.dart';
|
|
import 'package:appflowy/user/application/sign_in_bloc.dart';
|
|
|
|
+import 'package:appflowy/user/presentation/presentation.dart';
|
|
import 'package:appflowy/util/platform_extension.dart';
|
|
import 'package:appflowy/util/platform_extension.dart';
|
|
import 'package:appflowy/workspace/application/appearance.dart';
|
|
import 'package:appflowy/workspace/application/appearance.dart';
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
@@ -13,73 +14,31 @@ import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
|
|
|
|
class ThirdPartySignInButtons extends StatelessWidget {
|
|
class ThirdPartySignInButtons extends StatelessWidget {
|
|
- /// Used in DesktopSignInScreen and MobileSignInScreen
|
|
|
|
|
|
+ /// Used in DesktopSignInScreen, MobileSignInScreen and SettingThirdPartyLogin
|
|
const ThirdPartySignInButtons({
|
|
const ThirdPartySignInButtons({
|
|
super.key,
|
|
super.key,
|
|
});
|
|
});
|
|
|
|
|
|
@override
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
Widget build(BuildContext context) {
|
|
- final isMobile = PlatformExtension.isMobile;
|
|
|
|
-
|
|
|
|
// Get themeMode from AppearanceSettingsCubit
|
|
// Get themeMode from AppearanceSettingsCubit
|
|
// When user changes themeMode, it changes the state in AppearanceSettingsCubit, but the themeMode for the MaterialApp won't change, it only got updated(get value from AppearanceSettingsCubit) when user open the app again. Thus, we should get themeMode from AppearanceSettingsCubit rather than MediaQuery.
|
|
// When user changes themeMode, it changes the state in AppearanceSettingsCubit, but the themeMode for the MaterialApp won't change, it only got updated(get value from AppearanceSettingsCubit) when user open the app again. Thus, we should get themeMode from AppearanceSettingsCubit rather than MediaQuery.
|
|
final isDarkMode =
|
|
final isDarkMode =
|
|
context.read<AppearanceSettingsCubit>().state.themeMode ==
|
|
context.read<AppearanceSettingsCubit>().state.themeMode ==
|
|
ThemeMode.dark;
|
|
ThemeMode.dark;
|
|
|
|
|
|
- if (isMobile) {
|
|
|
|
- // ThirdPartySignInButtons in mobile
|
|
|
|
- return Column(
|
|
|
|
- children: [
|
|
|
|
- _ThirdPartySignInButton(
|
|
|
|
- isMobile: true,
|
|
|
|
- icon: FlowySvgs.google_mark_xl,
|
|
|
|
- labelText: LocaleKeys.signIn_LogInWithGoogle.tr(),
|
|
|
|
- onPressed: () {
|
|
|
|
- _signInWithGoogle(context);
|
|
|
|
- },
|
|
|
|
- ),
|
|
|
|
- const SizedBox(height: 8),
|
|
|
|
- _ThirdPartySignInButton(
|
|
|
|
- isMobile: true,
|
|
|
|
- icon: isDarkMode
|
|
|
|
- ? FlowySvgs.github_mark_white_xl
|
|
|
|
- : FlowySvgs.github_mark_black_xl,
|
|
|
|
- labelText: LocaleKeys.signIn_LogInWithGithub.tr(),
|
|
|
|
- onPressed: () {
|
|
|
|
- _signInWithGithub(context);
|
|
|
|
- },
|
|
|
|
- ),
|
|
|
|
- const SizedBox(height: 8),
|
|
|
|
- _ThirdPartySignInButton(
|
|
|
|
- isMobile: true,
|
|
|
|
- icon: isDarkMode
|
|
|
|
- ? FlowySvgs.discord_mark_white_xl
|
|
|
|
- : FlowySvgs.discord_mark_blurple_xl,
|
|
|
|
- labelText: LocaleKeys.signIn_LogInWithDiscord.tr(),
|
|
|
|
- onPressed: () {
|
|
|
|
- _signInWithDiscord(context);
|
|
|
|
- },
|
|
|
|
- ),
|
|
|
|
- ],
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
- // ThirdPartySignInButtons in desktop
|
|
|
|
return Column(
|
|
return Column(
|
|
children: [
|
|
children: [
|
|
_ThirdPartySignInButton(
|
|
_ThirdPartySignInButton(
|
|
key: const Key('signInWithGoogleButton'),
|
|
key: const Key('signInWithGoogleButton'),
|
|
- isMobile: false,
|
|
|
|
icon: FlowySvgs.google_mark_xl,
|
|
icon: FlowySvgs.google_mark_xl,
|
|
labelText: LocaleKeys.signIn_LogInWithGoogle.tr(),
|
|
labelText: LocaleKeys.signIn_LogInWithGoogle.tr(),
|
|
onPressed: () {
|
|
onPressed: () {
|
|
_signInWithGoogle(context);
|
|
_signInWithGoogle(context);
|
|
},
|
|
},
|
|
),
|
|
),
|
|
- const SizedBox(height: 8),
|
|
|
|
|
|
+ const VSpace(8),
|
|
_ThirdPartySignInButton(
|
|
_ThirdPartySignInButton(
|
|
- isMobile: false,
|
|
|
|
icon: isDarkMode
|
|
icon: isDarkMode
|
|
? FlowySvgs.github_mark_white_xl
|
|
? FlowySvgs.github_mark_white_xl
|
|
: FlowySvgs.github_mark_black_xl,
|
|
: FlowySvgs.github_mark_black_xl,
|
|
@@ -88,9 +47,8 @@ class ThirdPartySignInButtons extends StatelessWidget {
|
|
_signInWithGithub(context);
|
|
_signInWithGithub(context);
|
|
},
|
|
},
|
|
),
|
|
),
|
|
- const SizedBox(height: 8),
|
|
|
|
|
|
+ const VSpace(8),
|
|
_ThirdPartySignInButton(
|
|
_ThirdPartySignInButton(
|
|
- isMobile: false,
|
|
|
|
icon: isDarkMode
|
|
icon: isDarkMode
|
|
? FlowySvgs.discord_mark_white_xl
|
|
? FlowySvgs.discord_mark_white_xl
|
|
: FlowySvgs.discord_mark_blurple_xl,
|
|
: FlowySvgs.discord_mark_blurple_xl,
|
|
@@ -105,15 +63,14 @@ class ThirdPartySignInButtons extends StatelessWidget {
|
|
}
|
|
}
|
|
|
|
|
|
class _ThirdPartySignInButton extends StatelessWidget {
|
|
class _ThirdPartySignInButton extends StatelessWidget {
|
|
|
|
+ /// Build button based on current Platform(mobile or desktop).
|
|
const _ThirdPartySignInButton({
|
|
const _ThirdPartySignInButton({
|
|
super.key,
|
|
super.key,
|
|
- required this.isMobile,
|
|
|
|
required this.icon,
|
|
required this.icon,
|
|
required this.labelText,
|
|
required this.labelText,
|
|
required this.onPressed,
|
|
required this.onPressed,
|
|
});
|
|
});
|
|
|
|
|
|
- final bool isMobile;
|
|
|
|
final FlowySvgData icon;
|
|
final FlowySvgData icon;
|
|
final String labelText;
|
|
final String labelText;
|
|
|
|
|
|
@@ -122,39 +79,44 @@ class _ThirdPartySignInButton extends StatelessWidget {
|
|
@override
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
Widget build(BuildContext context) {
|
|
final style = Theme.of(context);
|
|
final style = Theme.of(context);
|
|
- final buttonSize = MediaQuery.of(context).size;
|
|
|
|
|
|
+ final isMobile = PlatformExtension.isMobile;
|
|
if (isMobile) {
|
|
if (isMobile) {
|
|
- return SizedBox(
|
|
|
|
- width: double.infinity,
|
|
|
|
- height: 48,
|
|
|
|
- child: OutlinedButton.icon(
|
|
|
|
- icon: Container(
|
|
|
|
- width: buttonSize.width / 5.5,
|
|
|
|
- alignment: Alignment.centerRight,
|
|
|
|
- child: SizedBox(
|
|
|
|
- width: 24,
|
|
|
|
- child: FlowySvg(
|
|
|
|
- icon,
|
|
|
|
- blendMode: null,
|
|
|
|
|
|
+ // Use LayoutBuilder to get the maxWidth of parent widget(Column) and set the icon occupied area to 1/4 of maxWidth.
|
|
|
|
+ return LayoutBuilder(
|
|
|
|
+ builder: (context, constraints) {
|
|
|
|
+ return SizedBox(
|
|
|
|
+ height: 48,
|
|
|
|
+ child: OutlinedButton.icon(
|
|
|
|
+ icon: Container(
|
|
|
|
+ width: constraints.maxWidth / 4,
|
|
|
|
+ alignment: Alignment.centerRight,
|
|
|
|
+ child: SizedBox(
|
|
|
|
+ width: 24,
|
|
|
|
+ child: FlowySvg(
|
|
|
|
+ icon,
|
|
|
|
+ blendMode: null,
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
),
|
|
),
|
|
|
|
+ label: Container(
|
|
|
|
+ padding: const EdgeInsets.only(left: 4),
|
|
|
|
+ alignment: Alignment.centerLeft,
|
|
|
|
+ child: Text(labelText),
|
|
|
|
+ ),
|
|
|
|
+ onPressed: onPressed,
|
|
),
|
|
),
|
|
- ),
|
|
|
|
- label: Container(
|
|
|
|
- padding: const EdgeInsets.only(left: 4),
|
|
|
|
- alignment: Alignment.centerLeft,
|
|
|
|
- child: Text(labelText),
|
|
|
|
- ),
|
|
|
|
- onPressed: onPressed,
|
|
|
|
- ),
|
|
|
|
|
|
+ );
|
|
|
|
+ },
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
+ // In desktop, the width of button is limited by [AuthFormContainer]
|
|
return SizedBox(
|
|
return SizedBox(
|
|
height: 48,
|
|
height: 48,
|
|
- width: double.infinity,
|
|
|
|
|
|
+ width: AuthFormContainer.width,
|
|
child: OutlinedButton.icon(
|
|
child: OutlinedButton.icon(
|
|
// In order to align all the labels vertically in a relatively centered position to the button, we use a fixed width container to wrap the icon(align to the right), then use another container to align the label to left.
|
|
// In order to align all the labels vertically in a relatively centered position to the button, we use a fixed width container to wrap the icon(align to the right), then use another container to align the label to left.
|
|
icon: Container(
|
|
icon: Container(
|
|
- width: buttonSize.width / 8,
|
|
|
|
|
|
+ width: AuthFormContainer.width / 4,
|
|
alignment: Alignment.centerRight,
|
|
alignment: Alignment.centerRight,
|
|
child: SizedBox(
|
|
child: SizedBox(
|
|
// Some icons are not square, so we just use a fixed width here.
|
|
// Some icons are not square, so we just use a fixed width here.
|