diff --git a/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart b/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart index e01e02c6e1..51df6d6b14 100644 --- a/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart +++ b/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart @@ -12,7 +12,7 @@ import 'util.dart'; extension AppFlowyAuthTest on WidgetTester { Future tapGoogleLoginInButton() async { await tapButton( - find.byKey(const Key('signInWithGoogleButton')), + find.byKey(signInWithGoogleButtonKey), ); } @@ -36,7 +36,7 @@ extension AppFlowyAuthTest on WidgetTester { } void expectToSeeGoogleLoginButton() { - expect(find.byKey(const Key('signInWithGoogleButton')), findsOneWidget); + expect(find.byKey(signInWithGoogleButtonKey), findsOneWidget); } void assertSwitchValue(Finder finder, bool value) { diff --git a/frontend/appflowy_flutter/ios/Runner.xcodeproj/project.pbxproj b/frontend/appflowy_flutter/ios/Runner.xcodeproj/project.pbxproj index aa53cf9b88..804ad052be 100644 --- a/frontend/appflowy_flutter/ios/Runner.xcodeproj/project.pbxproj +++ b/frontend/appflowy_flutter/ios/Runner.xcodeproj/project.pbxproj @@ -372,6 +372,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = AppFlowy; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -383,6 +384,8 @@ STRIP_STYLE = "non-global"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; @@ -511,6 +514,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = AppFlowy; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -522,6 +526,8 @@ STRIP_STYLE = "non-global"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -545,6 +551,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = AppFlowy; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -556,6 +563,8 @@ STRIP_STYLE = "non-global"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; diff --git a/frontend/appflowy_flutter/ios/Runner/Info.plist b/frontend/appflowy_flutter/ios/Runner/Info.plist index 5ec528b05e..cca5b3716c 100644 --- a/frontend/appflowy_flutter/ios/Runner/Info.plist +++ b/frontend/appflowy_flutter/ios/Runner/Info.plist @@ -1,75 +1,73 @@ - - NSCameraUsageDescription - AppFlowy requires access to the camera. - NSPhotoLibraryUsageDescription - AppFlowy requires access to the photo library. - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLocalizations - - en - - FLTEnableImpeller - - CFBundleName - AppFlowy - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleURLTypes - - - CFBundleURLName - - CFBundleURLSchemes - - appflowy-flutter - - - - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UIApplicationSupportsIndirectInputEvents - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - NSAppTransportSecurity + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLocalizations + + en + + CFBundleName + AppFlowy + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleURLTypes + - NSAllowsArbitraryLoads - + CFBundleURLName + + CFBundleURLSchemes + + appflowy-flutter + + + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + FLTEnableImpeller + + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + - \ No newline at end of file + NSCameraUsageDescription + AppFlowy requires access to the camera. + NSPhotoLibraryUsageDescription + AppFlowy requires access to the photo library. + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/frontend/appflowy_flutter/ios/Runner/Runner.entitlements b/frontend/appflowy_flutter/ios/Runner/Runner.entitlements index 903def2af5..80b5221de7 100644 --- a/frontend/appflowy_flutter/ios/Runner/Runner.entitlements +++ b/frontend/appflowy_flutter/ios/Runner/Runner.entitlements @@ -4,5 +4,9 @@ aps-environment development + com.apple.developer.applesignin + + Default + diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/bottom_sheet_rename_widget.dart b/frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/bottom_sheet_rename_widget.dart index cabc234fec..8ac4d9b20e 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/bottom_sheet_rename_widget.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/bottom_sheet_rename_widget.dart @@ -65,7 +65,7 @@ class _MobileBottomSheetRenameWidgetState padding: const EdgeInsets.symmetric( horizontal: 16.0, ), - textColor: Colors.white, + fontColor: Colors.white, fillColor: Theme.of(context).primaryColor, onPressed: () { widget.onRename(controller.text); diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/setting/cloud/appflowy_cloud_page.dart b/frontend/appflowy_flutter/lib/mobile/presentation/setting/cloud/appflowy_cloud_page.dart index 3ce8e57b36..24c50f7ae6 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/setting/cloud/appflowy_cloud_page.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/setting/cloud/appflowy_cloud_page.dart @@ -16,13 +16,10 @@ class AppFlowyCloudPage extends StatelessWidget { appBar: FlowyAppBar( titleText: LocaleKeys.settings_menu_cloudSettings.tr(), ), - body: Padding( - padding: const EdgeInsets.all(20.0), - child: SettingCloud( - restartAppFlowy: () async { - await runAppFlowy(); - }, - ), + body: SettingCloud( + restartAppFlowy: () async { + await runAppFlowy(); + }, ), ); } diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/setting/user_session_setting_group.dart b/frontend/appflowy_flutter/lib/mobile/presentation/setting/user_session_setting_group.dart index 1145d08048..1d91c3b9f6 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/setting/user_session_setting_group.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/setting/user_session_setting_group.dart @@ -33,7 +33,9 @@ class UserSessionSettingGroup extends StatelessWidget { ); }, builder: (context, state) { - return const ThirdPartySignInButtons(); + return const ThirdPartySignInButtons( + expanded: true, + ); }, ), ), diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/checklist_cell_editor.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/checklist_cell_editor.dart index ba2dc28702..15fe9b59ff 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/checklist_cell_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/checklist_cell_editor.dart @@ -372,7 +372,7 @@ class _NewTaskItemState extends State { ? Theme.of(context).disabledColor : Theme.of(context).colorScheme.primaryContainer, fontColor: Theme.of(context).colorScheme.onPrimary, - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), onPressed: _textEditingController.text.isEmpty ? null : () { diff --git a/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_auth_service.dart b/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_auth_service.dart index 81dd8ed9cf..ae7fe37982 100644 --- a/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_auth_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_auth_service.dart @@ -121,6 +121,8 @@ extension ProviderTypePBExtension on ProviderTypePB { return ProviderTypePB.Google; case 'discord': return ProviderTypePB.Discord; + case 'apple': + return ProviderTypePB.Apple; default: throw UnimplementedError(); } diff --git a/frontend/appflowy_flutter/lib/user/application/sign_in_bloc.dart b/frontend/appflowy_flutter/lib/user/application/sign_in_bloc.dart index 52a103899c..6fda156567 100644 --- a/frontend/appflowy_flutter/lib/user/application/sign_in_bloc.dart +++ b/frontend/appflowy_flutter/lib/user/application/sign_in_bloc.dart @@ -1,16 +1,16 @@ -import 'package:flutter/foundation.dart'; - import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/generated/locale_keys.g.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:appflowy_backend/log.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:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -208,6 +208,8 @@ class SignInBloc extends Bloc { } SignInState _stateFromCode(FlowyError error) { + Log.error('SignInState _stateFromCode: ${error.msg}'); + switch (error.code) { case ErrorCode.EmailFormatInvalid: return state.copyWith( diff --git a/frontend/appflowy_flutter/lib/user/presentation/helpers/handle_open_workspace_error.dart b/frontend/appflowy_flutter/lib/user/presentation/helpers/handle_open_workspace_error.dart index 3ecacf0961..a6375e0c4e 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/helpers/handle_open_workspace_error.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/helpers/handle_open_workspace_error.dart @@ -1,11 +1,12 @@ import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/presentation/router.dart'; +import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; -import 'package:flowy_infra_ui/style_widget/snap_bar.dart'; import 'package:flutter/material.dart'; +import 'package:toastification/toastification.dart'; void handleOpenWorkspaceError(BuildContext context, FlowyError error) { Log.error(error); @@ -15,24 +16,24 @@ void handleOpenWorkspaceError(BuildContext context, FlowyError error) { getIt().pushWorkspaceErrorScreen(context, userFolder, error); break; case ErrorCode.InvalidEncryptSecret: - showSnapBar( + case ErrorCode.HttpError: + showToastNotification( context, - error.msg, + message: error.msg, + type: ToastificationType.error, ); break; - case ErrorCode.HttpError: - showSnapBar( - context, - error.msg, - ); default: - showSnapBar( + showToastNotification( context, - error.msg, - onClosed: () { - getIt().signOut(); - runAppFlowy(); - }, + message: error.msg, + type: ToastificationType.error, + callbacks: ToastificationCallbacks( + onDismissed: (_) { + getIt().signOut(); + runAppFlowy(); + }, + ), ); } } diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/desktop_sign_in_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/desktop_sign_in_screen.dart index 89b782d231..7c023befea 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/desktop_sign_in_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/desktop_sign_in_screen.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/core/frameless_window.dart'; import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; @@ -10,6 +8,7 @@ import 'package:appflowy/user/presentation/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/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class DesktopSignInScreen extends StatelessWidget { @@ -45,14 +44,14 @@ class DesktopSignInScreen extends StatelessWidget { if (isAuthEnabled) ...[ const _OrDivider(), - const VSpace(10), + const VSpace(20), const ThirdPartySignInButtons(), ], const VSpace(20), // anonymous sign in const SignInAnonymousButtonV2(), - const VSpace(10), + const VSpace(16), // sign in agreement const SignInAgreement(), diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/mobile_sign_in_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/mobile_sign_in_screen.dart index ce0e959aca..5526cb6c70 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/mobile_sign_in_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/mobile_sign_in_screen.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +import 'dart:io'; import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart'; @@ -8,6 +8,7 @@ import 'package:appflowy/user/application/sign_in_bloc.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'; import 'package:go_router/go_router.dart'; @@ -23,26 +24,26 @@ class MobileSignInScreen extends StatelessWidget { return BlocBuilder( builder: (context, state) { return Scaffold( + resizeToAvoidBottomInset: false, body: Padding( - padding: const EdgeInsets.symmetric(vertical: 50, horizontal: 40), + padding: const EdgeInsets.symmetric(vertical: 38, horizontal: 40), child: Column( children: [ const Spacer(flex: 4), _buildLogo(), - const VSpace(spacing * 2), - _buildWelcomeText(), + const VSpace(spacing), _buildAppNameText(colorScheme), const VSpace(spacing * 2), const SignInWithMagicLinkButtons(), const VSpace(spacing), if (isAuthEnabled) _buildThirdPartySignInButtons(colorScheme), - const VSpace(spacing), - const SignInAnonymousButtonV2(), - const VSpace(spacing), + const VSpace(spacing * 1.5), const SignInAgreement(), const VSpace(spacing), - _buildSettingsButton(context), if (!isAuthEnabled) const Spacer(flex: 2), + const Spacer(flex: 2), + const Spacer(), + Expanded(child: _buildSettingsButton(context)), ], ), ), @@ -51,19 +52,10 @@ class MobileSignInScreen extends StatelessWidget { ); } - Widget _buildWelcomeText() { - return FlowyText( - LocaleKeys.welcomeTo.tr(), - textAlign: TextAlign.center, - fontSize: 32, - fontWeight: FontWeight.w700, - ); - } - Widget _buildLogo() { return const FlowySvg( FlowySvgs.flowy_logo_xl, - size: Size.square(64), + size: Size.square(56), blendMode: null, ); } @@ -72,7 +64,7 @@ class MobileSignInScreen extends StatelessWidget { return FlowyText( LocaleKeys.appName.tr(), textAlign: TextAlign.center, - fontSize: 32, + fontSize: 28, color: const Color(0xFF00BCF0), fontWeight: FontWeight.w700, ); @@ -89,6 +81,7 @@ class MobileSignInScreen extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 8), child: FlowyText( LocaleKeys.signIn_or.tr(), + fontSize: 12, color: colorScheme.onSecondary, ), ), @@ -96,23 +89,45 @@ class MobileSignInScreen extends StatelessWidget { ], ), const VSpace(16), - const ThirdPartySignInButtons(), + // expand third-party sign in buttons on Android by default. + // on iOS, the github and discord buttons are collapsed by default. + ThirdPartySignInButtons( + expanded: Platform.isAndroid, + ), ], ); } Widget _buildSettingsButton(BuildContext context) { - return FlowyButton( - text: FlowyText( - LocaleKeys.signIn_settings.tr(), - textAlign: TextAlign.center, - fontSize: 12.0, - fontWeight: FontWeight.w500, - decoration: TextDecoration.underline, - ), - onTap: () { - context.push(MobileLaunchSettingsPage.routeName); - }, + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + FlowyButton( + useIntrinsicWidth: true, + text: FlowyText( + LocaleKeys.signIn_settings.tr(), + textAlign: TextAlign.center, + fontSize: 12.0, + // fontWeight: FontWeight.w500, + color: Colors.grey, + decoration: TextDecoration.underline, + ), + onTap: () { + context.push(MobileLaunchSettingsPage.routeName); + }, + ), + const HSpace(24), + SignInAnonymousButtonV2( + child: FlowyText( + LocaleKeys.signIn_anonymous.tr(), + textAlign: TextAlign.center, + fontSize: 12.0, + // fontWeight: FontWeight.w500, + color: Colors.grey, + decoration: TextDecoration.underline, + ), + ), + ], ); } } diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/sign_in_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/sign_in_screen.dart index 731faed73e..8935001624 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/sign_in_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/sign_in_screen.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/user/application/sign_in_bloc.dart'; import 'package:appflowy/user/presentation/router.dart'; @@ -7,6 +5,7 @@ import 'package:appflowy/user/presentation/screens/sign_in_screen/desktop_sign_i 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'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../helpers/helpers.dart'; @@ -21,16 +20,7 @@ class SignInScreen extends StatelessWidget { return BlocProvider( create: (context) => getIt(), child: BlocConsumer( - listener: (context, state) { - final successOrFail = state.successOrFail; - if (successOrFail != null) { - handleUserProfileResult( - successOrFail, - context, - getIt(), - ); - } - }, + listener: _showSignInError, builder: (context, state) { final isLoading = context.read().state.isSubmitting; if (PlatformExtension.isMobile) { @@ -43,4 +33,15 @@ class SignInScreen extends StatelessWidget { ), ); } + + void _showSignInError(BuildContext context, SignInState state) { + final successOrFail = state.successOrFail; + if (successOrFail != null) { + handleUserProfileResult( + successOrFail, + context, + getIt(), + ); + } + } } diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/magic_link_sign_in_buttons.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/magic_link_sign_in_buttons.dart index e32a9e2908..d95f3ecbcf 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/magic_link_sign_in_buttons.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/magic_link_sign_in_buttons.dart @@ -34,11 +34,19 @@ class _SignInWithMagicLinkButtonsState crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - height: 48.0, + height: PlatformExtension.isMobile ? 38.0 : 48.0, child: FlowyTextField( autoFocus: false, controller: controller, + borderRadius: BorderRadius.circular(4.0), hintText: LocaleKeys.signIn_pleaseInputYourEmail.tr(), + hintStyle: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 14.0, + color: Theme.of(context).hintColor, + ), + textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontSize: 14.0, + ), keyboardType: TextInputType.emailAddress, onSubmitted: (_) => _sendMagicLink(context, controller.text), ), @@ -88,14 +96,14 @@ class _ConfirmButton extends StatelessWidget { if (PlatformExtension.isMobile) { return ElevatedButton( style: ElevatedButton.styleFrom( - minimumSize: const Size(double.infinity, 56), + minimumSize: const Size(double.infinity, 32), + maximumSize: const Size(double.infinity, 38), ), onPressed: onTap, child: FlowyText( name, fontSize: 14, color: Theme.of(context).colorScheme.onPrimary, - fontWeight: FontWeight.w500, ), ); } else { @@ -108,6 +116,7 @@ class _ConfirmButton extends StatelessWidget { text: FlowyText.medium( name, textAlign: TextAlign.center, + color: Theme.of(context).colorScheme.onPrimary, ), radius: Corners.s6Border, ), diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_agreement.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_agreement.dart index 7976e63667..7351871b6a 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_agreement.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_agreement.dart @@ -21,7 +21,11 @@ class SignInAgreement extends StatelessWidget { ), TextSpan( text: '${LocaleKeys.web_termOfUse.tr()} ', - style: const TextStyle(color: Colors.blue, fontSize: 12), + style: const TextStyle( + color: Colors.grey, + fontSize: 12, + decoration: TextDecoration.underline, + ), mouseCursor: SystemMouseCursors.click, recognizer: TapGestureRecognizer() ..onTap = () => afLaunchUrlString('https://appflowy.io/terms'), @@ -32,7 +36,11 @@ class SignInAgreement extends StatelessWidget { ), TextSpan( text: LocaleKeys.web_privacyPolicy.tr(), - style: const TextStyle(color: Colors.blue, fontSize: 12), + style: const TextStyle( + color: Colors.grey, + fontSize: 12, + decoration: TextDecoration.underline, + ), mouseCursor: SystemMouseCursors.click, recognizer: TapGestureRecognizer() ..onTap = () => afLaunchUrlString('https://appflowy.io/privacy'), diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_anonymous_button.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_anonymous_button.dart index e8d6bac536..e12582b9cd 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_anonymous_button.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_anonymous_button.dart @@ -89,8 +89,11 @@ class SignInAnonymousButton extends StatelessWidget { class SignInAnonymousButtonV2 extends StatelessWidget { const SignInAnonymousButtonV2({ super.key, + this.child, }); + final Widget? child; + @override Widget build(BuildContext context) { return BlocBuilder( @@ -126,11 +129,12 @@ class SignInAnonymousButtonV2 extends StatelessWidget { cursor: SystemMouseCursors.click, child: GestureDetector( onTap: onTap, - child: FlowyText( - text, - color: Colors.blue, - fontSize: 12, - ), + child: child ?? + FlowyText( + text, + color: Colors.blue, + fontSize: 12, + ), ), ); }, diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_or_logout_button.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_or_logout_button.dart index e25fcf3a35..58509aee5a 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_or_logout_button.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/sign_in_or_logout_button.dart @@ -20,7 +20,7 @@ class MobileSignInOrLogoutButton extends StatelessWidget { return GestureDetector( onTap: onPressed, child: Container( - height: 48, + height: 38, decoration: BoxDecoration( borderRadius: const BorderRadius.all( Radius.circular(4), @@ -54,7 +54,7 @@ class MobileSignInOrLogoutButton extends StatelessWidget { FlowyText( labelText, fontSize: 14.0, - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w400, ), ], ), diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/third_party_sign_in_button.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/third_party_sign_in_button.dart new file mode 100644 index 0000000000..47c6ea515f --- /dev/null +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/third_party_sign_in_button.dart @@ -0,0 +1,137 @@ +import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/mobile/presentation/base/gesture.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/material.dart'; + +enum ThirdPartySignInButtonType { + apple, + google, + github, + discord, + anonymous; + + FlowySvgData get icon { + switch (this) { + case ThirdPartySignInButtonType.apple: + return FlowySvgs.m_apple_icon_xl; + case ThirdPartySignInButtonType.google: + return FlowySvgs.m_google_icon_xl; + case ThirdPartySignInButtonType.github: + return FlowySvgs.m_github_icon_xl; + case ThirdPartySignInButtonType.discord: + return FlowySvgs.m_discord_icon_xl; + case ThirdPartySignInButtonType.anonymous: + return FlowySvgs.m_discord_icon_xl; + } + } + + String get labelText { + switch (this) { + case ThirdPartySignInButtonType.apple: + return LocaleKeys.signIn_signInWithApple.tr(); + case ThirdPartySignInButtonType.google: + return LocaleKeys.signIn_signInWithGoogle.tr(); + case ThirdPartySignInButtonType.github: + return LocaleKeys.signIn_signInWithGithub.tr(); + case ThirdPartySignInButtonType.discord: + return LocaleKeys.signIn_signInWithDiscord.tr(); + case ThirdPartySignInButtonType.anonymous: + return 'Anonymous session'; + } + } + + // https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple + Color backgroundColor(BuildContext context) { + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + switch (this) { + case ThirdPartySignInButtonType.apple: + return isDarkMode ? Colors.white : Colors.black; + case ThirdPartySignInButtonType.google: + case ThirdPartySignInButtonType.github: + case ThirdPartySignInButtonType.discord: + case ThirdPartySignInButtonType.anonymous: + return isDarkMode ? Colors.black : Colors.grey.shade100; + } + } + + Color textColor(BuildContext context) { + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + switch (this) { + case ThirdPartySignInButtonType.apple: + return isDarkMode ? Colors.black : Colors.white; + case ThirdPartySignInButtonType.google: + case ThirdPartySignInButtonType.github: + case ThirdPartySignInButtonType.discord: + case ThirdPartySignInButtonType.anonymous: + return isDarkMode ? Colors.white : Colors.black; + } + } + + BlendMode? get blendMode { + switch (this) { + case ThirdPartySignInButtonType.apple: + case ThirdPartySignInButtonType.github: + return BlendMode.srcIn; + default: + return null; + } + } +} + +class MobileThirdPartySignInButton extends StatelessWidget { + const MobileThirdPartySignInButton({ + super.key, + this.height = 38, + this.fontSize = 14.0, + required this.onPressed, + required this.type, + }); + + final VoidCallback onPressed; + final double height; + final double fontSize; + final ThirdPartySignInButtonType type; + + @override + Widget build(BuildContext context) { + final style = Theme.of(context); + + return AnimatedGestureDetector( + scaleFactor: 1.0, + onTapUp: onPressed, + child: Container( + height: height, + decoration: BoxDecoration( + color: type.backgroundColor(context), + borderRadius: const BorderRadius.all( + Radius.circular(4), + ), + border: Border.all( + color: style.colorScheme.outline, + width: 0.5, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (type != ThirdPartySignInButtonType.anonymous) + FlowySvg( + type.icon, + size: Size.square(fontSize), + blendMode: type.blendMode, + color: type.textColor(context), + ), + const HSpace(8.0), + FlowyText( + type.labelText, + fontSize: fontSize, + color: type.textColor(context), + ), + ], + ), + ), + ); + } +} diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/third_party_sign_in_buttons.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/third_party_sign_in_buttons.dart index b7fe53a8ea..6972eb2105 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/third_party_sign_in_buttons.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/third_party_sign_in_buttons.dart @@ -1,126 +1,167 @@ -import 'package:flutter/material.dart'; +import 'dart:io'; 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'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -class ThirdPartySignInButtons extends StatelessWidget { +import 'third_party_sign_in_button.dart'; + +@visibleForTesting +const Key signInWithGoogleButtonKey = Key('signInWithGoogleButton'); + +class ThirdPartySignInButtons extends StatefulWidget { /// Used in DesktopSignInScreen, MobileSignInScreen and SettingThirdPartyLogin - const ThirdPartySignInButtons({super.key}); - - @override - Widget build(BuildContext context) { - // 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. - - final themeModeFromCubit = - context.watch().state.themeMode; - - final isDarkMode = themeModeFromCubit == ThemeMode.system - ? MediaQuery.of(context).platformBrightness == Brightness.dark - : themeModeFromCubit == ThemeMode.dark; - - return BlocBuilder( - builder: (context, state) { - final (googleText, githubText, discordText) = switch (state.loginType) { - LoginType.signIn => ( - LocaleKeys.signIn_signInWithGoogle.tr(), - LocaleKeys.signIn_signInWithGithub.tr(), - LocaleKeys.signIn_signInWithDiscord.tr() - ), - LoginType.signUp => ( - LocaleKeys.signIn_signUpWithGoogle.tr(), - LocaleKeys.signIn_signUpWithGithub.tr(), - LocaleKeys.signIn_signUpWithDiscord.tr() - ), - }; - return Column( - children: [ - _ThirdPartySignInButton( - key: const Key('signInWithGoogleButton'), - icon: FlowySvgs.google_mark_xl, - labelText: googleText, - onPressed: () { - _signInWithGoogle(context); - }, - ), - const VSpace(8), - _ThirdPartySignInButton( - icon: isDarkMode - ? FlowySvgs.github_mark_white_xl - : FlowySvgs.github_mark_black_xl, - labelText: githubText, - onPressed: () { - _signInWithGithub(context); - }, - ), - const VSpace(8), - _ThirdPartySignInButton( - icon: isDarkMode - ? FlowySvgs.discord_mark_white_xl - : FlowySvgs.discord_mark_blurple_xl, - labelText: discordText, - onPressed: () { - _signInWithDiscord(context); - }, - ), - ], - ); - }, - ); - } -} - -class _ThirdPartySignInButton extends StatelessWidget { - /// Build button based on current Platform(mobile or desktop). - const _ThirdPartySignInButton({ + const ThirdPartySignInButtons({ super.key, - required this.icon, - required this.labelText, - required this.onPressed, + this.expanded = false, }); - final FlowySvgData icon; - final String labelText; + final bool expanded; - final VoidCallback onPressed; + @override + State createState() => + _ThirdPartySignInButtonsState(); +} + +class _ThirdPartySignInButtonsState extends State { + bool expanded = false; + + @override + void initState() { + super.initState(); + + expanded = widget.expanded; + } @override Widget build(BuildContext context) { - if (PlatformExtension.isMobile) { - return MobileSignInOrLogoutButton( - icon: icon, - labelText: labelText, - onPressed: onPressed, + if (PlatformExtension.isDesktopOrWeb) { + const padding = 16.0; + return Column( + children: [ + _DesktopSignInButton( + key: signInWithGoogleButtonKey, + type: ThirdPartySignInButtonType.google, + onPressed: () { + _signInWithGoogle(context); + }, + ), + const VSpace(padding), + _DesktopSignInButton( + type: ThirdPartySignInButtonType.github, + onPressed: () { + _signInWithGithub(context); + }, + ), + const VSpace(padding), + _DesktopSignInButton( + type: ThirdPartySignInButtonType.discord, + onPressed: () { + _signInWithDiscord(context); + }, + ), + ], ); } else { - return _DesktopSignInButton( - icon: icon, - labelText: labelText, - onPressed: onPressed, + const padding = 8.0; + return BlocBuilder( + builder: (context, state) { + return Column( + children: [ + if (Platform.isIOS) ...[ + MobileThirdPartySignInButton( + type: ThirdPartySignInButtonType.apple, + onPressed: () { + _signInWithApple(context); + }, + ), + const VSpace(padding), + ], + MobileThirdPartySignInButton( + type: ThirdPartySignInButtonType.google, + onPressed: () { + _signInWithGoogle(context); + }, + ), + if (expanded) ...[ + const VSpace(padding), + MobileThirdPartySignInButton( + type: ThirdPartySignInButtonType.github, + onPressed: () { + _signInWithGithub(context); + }, + ), + const VSpace(padding), + MobileThirdPartySignInButton( + type: ThirdPartySignInButtonType.discord, + onPressed: () { + _signInWithDiscord(context); + }, + ), + ], + if (!expanded) ...[ + const VSpace(padding * 2), + GestureDetector( + onTap: () { + setState(() { + expanded = !expanded; + }); + }, + child: FlowyText( + LocaleKeys.signIn_continueAnotherWay.tr(), + color: Theme.of(context).colorScheme.onSurface, + decoration: TextDecoration.underline, + fontSize: 14, + ), + ), + ], + ], + ); + }, ); } } + + void _signInWithApple(BuildContext context) { + context.read().add( + const SignInEvent.signedInWithOAuth('apple'), + ); + } + + void _signInWithGoogle(BuildContext context) { + context.read().add( + const SignInEvent.signedInWithOAuth('google'), + ); + } + + void _signInWithGithub(BuildContext context) { + context + .read() + .add(const SignInEvent.signedInWithOAuth('github')); + } + + void _signInWithDiscord(BuildContext context) { + context + .read() + .add(const SignInEvent.signedInWithOAuth('discord')); + } } class _DesktopSignInButton extends StatelessWidget { const _DesktopSignInButton({ - required this.icon, - required this.labelText, + super.key, + required this.type, required this.onPressed, }); - final FlowySvgData icon; - final String labelText; - + final ThirdPartySignInButtonType type; final VoidCallback onPressed; @override @@ -139,8 +180,8 @@ class _DesktopSignInButton extends StatelessWidget { // Some icons are not square, so we just use a fixed width here. width: 24, child: FlowySvg( - icon, - blendMode: null, + type.icon, + blendMode: type.blendMode, ), ), ), @@ -148,7 +189,7 @@ class _DesktopSignInButton extends StatelessWidget { padding: const EdgeInsets.only(left: 8), alignment: Alignment.centerLeft, child: FlowyText( - labelText, + type.labelText, fontSize: 14, ), ), @@ -177,19 +218,3 @@ class _DesktopSignInButton extends StatelessWidget { ); } } - -void _signInWithGoogle(BuildContext context) { - context.read().add( - const SignInEvent.signedInWithOAuth('google'), - ); -} - -void _signInWithGithub(BuildContext context) { - context.read().add(const SignInEvent.signedInWithOAuth('github')); -} - -void _signInWithDiscord(BuildContext context) { - context - .read() - .add(const SignInEvent.signedInWithOAuth('discord')); -} diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/widgets.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/widgets.dart index c1c2bfecf9..18e260a472 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/widgets.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/widgets.dart @@ -1,7 +1,7 @@ export 'magic_link_sign_in_buttons.dart'; export 'sign_in_anonymous_button.dart'; export 'sign_in_or_logout_button.dart'; - +export 'third_party_sign_in_button.dart'; // export 'switch_sign_in_sign_up_button.dart'; export 'third_party_sign_in_buttons.dart'; export 'sign_in_agreement.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/single_setting_action.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/single_setting_action.dart index bc48db3e9f..a356e3fd50 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/single_setting_action.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/single_setting_action.dart @@ -107,7 +107,6 @@ class SingleSettingAction extends StatelessWidget { radius: Corners.s8Border, hoverColor: hoverColor(context), fontColor: fontColor(context), - textColor: fontColor(context), fontHoverColor: fontHoverColor(context), borderColor: borderColor(context), fontSize: 12, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/date_picker/mobile_appflowy_date_picker.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/date_picker/mobile_appflowy_date_picker.dart index cdeec95e88..5047b73e63 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/date_picker/mobile_appflowy_date_picker.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/date_picker/mobile_appflowy_date_picker.dart @@ -447,7 +447,7 @@ class _IncludeTimePickerState extends State<_IncludeTimePicker> { LocaleKeys.button_confirm.tr(), constraints: const BoxConstraints.tightFor(height: 42), mainAxisAlignment: MainAxisAlignment.center, - textColor: Theme.of(context).colorScheme.onPrimary, + fontColor: Theme.of(context).colorScheme.onPrimary, fillColor: Theme.of(context).primaryColor, onPressed: () { if (isStartDay) { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart index aa22d39170..76a9421968 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart @@ -303,12 +303,14 @@ void showToastNotification( required String message, String? description, ToastificationType type = ToastificationType.success, + ToastificationCallbacks? callbacks, double bottomPadding = 100, }) { if (PlatformExtension.isMobile) { toastification.showCustom( alignment: Alignment.bottomCenter, autoCloseDuration: const Duration(milliseconds: 3000), + callbacks: callbacks ?? const ToastificationCallbacks(), builder: (_, __) => _MToast( message: message, type: type, diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart index 3b9ba09430..742fb9baff 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -297,7 +297,6 @@ class FlowyTextButton extends StatelessWidget { this.padding = const EdgeInsets.symmetric(horizontal: 8, vertical: 6), this.hoverColor, this.fillColor, - this.textColor, this.heading, this.radius, this.mainAxisAlignment = MainAxisAlignment.start, @@ -353,7 +352,6 @@ class FlowyTextButton extends StatelessWidget { final Widget? heading; final Color? hoverColor; final Color? fillColor; - final Color? textColor; final BorderRadius? radius; final MainAxisAlignment mainAxisAlignment; final String? tooltip; @@ -376,9 +374,10 @@ class FlowyTextButton extends StatelessWidget { children.add(FlowyText( text, overflow: overflow, - color: textColor, + color: fontColor ?? Theme.of(context).colorScheme.onPrimary, textAlign: TextAlign.center, lineHeight: lineHeight, + fontSize: fontSize, )); Widget child = Row( diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart index 32cc2fa1fc..d0780b1c89 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart @@ -38,6 +38,7 @@ class FlowyTextField extends StatefulWidget { final bool isDense; final bool readOnly; final Color? enableBorderColor; + final BorderRadius? borderRadius; const FlowyTextField({ super.key, @@ -74,6 +75,7 @@ class FlowyTextField extends StatefulWidget { this.isDense = true, this.readOnly = false, this.enableBorderColor, + this.borderRadius, }); @override @@ -180,7 +182,7 @@ class FlowyTextFieldState extends State { (widget.maxLines == null || widget.maxLines! > 1) ? 12 : 0, ), enabledBorder: OutlineInputBorder( - borderRadius: Corners.s8Border, + borderRadius: widget.borderRadius ?? Corners.s8Border, borderSide: BorderSide( color: widget.enableBorderColor ?? Theme.of(context).colorScheme.outline, @@ -202,7 +204,7 @@ class FlowyTextFieldState extends State { suffixText: widget.showCounter ? _suffixText() : "", counterText: "", focusedBorder: OutlineInputBorder( - borderRadius: Corners.s8Border, + borderRadius: widget.borderRadius ?? Corners.s8Border, borderSide: BorderSide( color: widget.readOnly ? widget.enableBorderColor ?? @@ -214,13 +216,13 @@ class FlowyTextFieldState extends State { borderSide: BorderSide( color: Theme.of(context).colorScheme.error, ), - borderRadius: Corners.s8Border, + borderRadius: widget.borderRadius ?? Corners.s8Border, ), focusedErrorBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.error, ), - borderRadius: Corners.s8Border, + borderRadius: widget.borderRadius ?? Corners.s8Border, ), prefixIcon: widget.prefixIcon, suffixIcon: widget.suffixIcon, diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/rounded_button.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/rounded_button.dart index a49b70c4d0..0fa181a1dd 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/rounded_button.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/rounded_button.dart @@ -51,11 +51,9 @@ class RoundedTextButton extends StatelessWidget { radius: borderRadius ?? Corners.s6Border, fontColor: textColor ?? Theme.of(context).colorScheme.onPrimary, fillColor: fillColor ?? Theme.of(context).colorScheme.primary, - textColor: textColor, hoverColor: hoverColor ?? Theme.of(context).colorScheme.primaryContainer, padding: padding, - ), ), ); diff --git a/frontend/resources/flowy_icons/40x/m_apple_icon.svg b/frontend/resources/flowy_icons/40x/m_apple_icon.svg new file mode 100644 index 0000000000..5ec0b2627c --- /dev/null +++ b/frontend/resources/flowy_icons/40x/m_apple_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/flowy_icons/40x/m_discord_icon.svg b/frontend/resources/flowy_icons/40x/m_discord_icon.svg new file mode 100644 index 0000000000..12842e2100 --- /dev/null +++ b/frontend/resources/flowy_icons/40x/m_discord_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/flowy_icons/40x/m_github_icon.svg b/frontend/resources/flowy_icons/40x/m_github_icon.svg new file mode 100644 index 0000000000..000c5f9213 --- /dev/null +++ b/frontend/resources/flowy_icons/40x/m_github_icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/frontend/resources/flowy_icons/40x/m_google_icon.svg b/frontend/resources/flowy_icons/40x/m_google_icon.svg new file mode 100644 index 0000000000..3f1aaeafe8 --- /dev/null +++ b/frontend/resources/flowy_icons/40x/m_google_icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index ff6b5fcfd5..683402e7b3 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -36,6 +36,7 @@ "loginButtonText": "Login", "loginStartWithAnonymous": "Continue with an anonymous session", "continueAnonymousUser": "Continue with an anonymous session", + "anonymous": "Anonymous", "buttonText": "Sign In", "signingInText": "Signing in...", "forgotPassword": "Forgot Password?", @@ -50,6 +51,8 @@ "signInWithGoogle": "Continue with Google", "signInWithGithub": "Continue with Github", "signInWithDiscord": "Continue with Discord", + "signInWithApple": "Continue with Apple", + "continueAnotherWay": "Continue another way", "signUpWithGoogle": "Sign up with Google", "signUpWithGithub": "Sign up with Github", "signUpWithDiscord": "Sign up with Discord", @@ -2367,7 +2370,7 @@ "continueWithGoogle": "Continue with Google", "continueWithGithub": "Continue with GitHub", "continueWithDiscord": "Continue with Discord", - "signInAgreement": "By clicking \"Continue\" above, you confirm that\nyou have read, understood, and agreed to\nAppFlowy's", + "signInAgreement": "By clicking \"Continue\" above, you agreed to AppFlowy's", "and": "and", "termOfUse": "Terms", "privacyPolicy": "Privacy Policy",