diff --git a/frontend/appflowy_flutter/lib/env/cloud_env.dart b/frontend/appflowy_flutter/lib/env/cloud_env.dart index 986fab128b..15f3ada42e 100644 --- a/frontend/appflowy_flutter/lib/env/cloud_env.dart +++ b/frontend/appflowy_flutter/lib/env/cloud_env.dart @@ -100,6 +100,10 @@ bool get isAuthEnabled { return false; } +bool get isLocalAuthEnabled { + return currentCloudType().isLocal; +} + /// Determines if AppFlowy Cloud is enabled. bool get isAppFlowyCloudEnabled { return currentCloudType().isAppFlowyCloudEnabled; 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 24c50f7ae6..02d620e559 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 @@ -1,6 +1,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/mobile/presentation/base/app_bar/app_bar.dart'; import 'package:appflowy/startup/startup.dart'; +import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/workspace/presentation/settings/widgets/setting_cloud.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -18,6 +19,7 @@ class AppFlowyCloudPage extends StatelessWidget { ), body: SettingCloud( restartAppFlowy: () async { + await getIt().signOut(); await runAppFlowy(); }, ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart index 3889a7d1d3..67ab383eba 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart @@ -1064,6 +1064,11 @@ TextStyle _buildTextStyleInTableCell( }) { TextStyle textStyle = configuration.textStyle(node, textSpan: textSpan); + textStyle = textStyle.copyWith( + fontFamily: textSpan?.style?.fontFamily, + fontSize: textSpan?.style?.fontSize, + ); + if (node.isInHeaderColumn || node.isInHeaderRow || node.isInBoldColumn || diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/undo_redo/custom_undo_redo_commands.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/undo_redo/custom_undo_redo_commands.dart index 9ea6477969..36ea3d2704 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/undo_redo/custom_undo_redo_commands.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/undo_redo/custom_undo_redo_commands.dart @@ -1,6 +1,8 @@ import 'package:appflowy/plugins/document/presentation/editor_notification.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/shared_context/shared_context.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; /// Undo /// @@ -14,10 +16,15 @@ final CommandShortcutEvent customUndoCommand = CommandShortcutEvent( command: 'ctrl+z', macOSCommand: 'cmd+z', handler: (editorState) { - // if the selection is null, it means the keyboard service is disabled - if (editorState.selection == null) { + final context = editorState.document.root.context; + if (context == null) { return KeyEventResult.ignored; } + final editorContext = context.read(); + if (editorContext.coverTitleFocusNode.hasFocus) { + return KeyEventResult.ignored; + } + EditorNotification.undo().post(); return KeyEventResult.handled; }, @@ -35,9 +42,15 @@ final CommandShortcutEvent customRedoCommand = CommandShortcutEvent( command: 'ctrl+y,ctrl+shift+z', macOSCommand: 'cmd+shift+z', handler: (editorState) { - if (editorState.selection == null) { + final context = editorState.document.root.context; + if (context == null) { return KeyEventResult.ignored; } + final editorContext = context.read(); + if (editorContext.coverTitleFocusNode.hasFocus) { + return KeyEventResult.ignored; + } + EditorNotification.redo().post(); return KeyEventResult.handled; }, 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 863aadc49c..2a9a6fe798 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 @@ -5,6 +5,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/mobile/presentation/setting/launch_settings_page.dart'; import 'package:appflowy/user/application/sign_in_bloc.dart'; +import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/anonymous_sign_in_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'; @@ -34,7 +35,9 @@ class MobileSignInScreen extends StatelessWidget { const VSpace(spacing), _buildAppNameText(colorScheme), const VSpace(spacing * 2), - const SignInWithMagicLinkButtons(), + isLocalAuthEnabled + ? const SignInAnonymousButtonV3() + : const SignInWithMagicLinkButtons(), const VSpace(spacing), if (isAuthEnabled) _buildThirdPartySignInButtons(colorScheme), const VSpace(spacing * 1.5), @@ -118,7 +121,9 @@ class MobileSignInScreen extends StatelessWidget { }, ), const HSpace(24), - const SignInAnonymousButtonV2(), + isLocalAuthEnabled + ? const ChangeCloudModeButton() + : const SignInAnonymousButtonV2(), ], ); } diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/anonymous_sign_in_button.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/anonymous_sign_in_button.dart new file mode 100644 index 0000000000..1e5d7fa531 --- /dev/null +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/anonymous_sign_in_button.dart @@ -0,0 +1,63 @@ +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/startup/startup.dart'; +import 'package:appflowy/user/application/anon_user_bloc.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 SignInAnonymousButtonV3 extends StatelessWidget { + const SignInAnonymousButtonV3({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, signInState) { + return BlocProvider( + create: (context) => AnonUserBloc() + ..add( + const AnonUserEvent.initial(), + ), + child: BlocListener( + listener: (context, state) async { + if (state.openedAnonUser != null) { + await runAppFlowy(); + } + }, + child: BlocBuilder( + builder: (context, state) { + final text = LocaleKeys.signUp_getStartedText.tr(); + final onTap = state.anonUsers.isEmpty + ? () { + context + .read() + .add(const SignInEvent.signedInAsGuest()); + } + : () { + final bloc = context.read(); + final user = bloc.state.anonUsers.first; + bloc.add(AnonUserEvent.openAnonUser(user)); + }; + return ElevatedButton( + style: ElevatedButton.styleFrom( + minimumSize: const Size(double.infinity, 32), + maximumSize: const Size(double.infinity, 38), + ), + onPressed: onTap, + child: FlowyText( + text, + fontSize: 14, + color: Theme.of(context).colorScheme.onPrimary, + ), + ); + }, + ), + ), + ); + }, + ); + } +} 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 7351871b6a..a5e0d9784d 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 @@ -1,4 +1,5 @@ import 'package:appflowy/core/helpers/url_launcher.dart'; +import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/gestures.dart'; @@ -16,7 +17,9 @@ class SignInAgreement extends StatelessWidget { text: TextSpan( children: [ TextSpan( - text: '${LocaleKeys.web_signInAgreement.tr()} ', + text: isLocalAuthEnabled + ? '${LocaleKeys.web_signInLocalAgreement.tr()} ' + : '${LocaleKeys.web_signInAgreement.tr()} ', style: const TextStyle(color: Colors.grey, fontSize: 12), ), TextSpan( 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 bce22a714d..7fe4584e97 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 @@ -1,3 +1,4 @@ +import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/user/application/anon_user_bloc.dart'; @@ -138,3 +139,29 @@ class SignInAnonymousButtonV2 extends StatelessWidget { ); } } + +class ChangeCloudModeButton extends StatelessWidget { + const ChangeCloudModeButton({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return FlowyButton( + useIntrinsicWidth: true, + text: FlowyText( + 'Cloud', + decoration: TextDecoration.underline, + color: Colors.grey, + fontSize: 12, + ), + onTap: () async { + await useAppFlowyBetaCloudWithURL( + kAppflowyCloudUrl, + AuthenticatorType.appflowyCloud, + ); + await runAppFlowy(); + }, + ); + } +} diff --git a/frontend/appflowy_flutter/macos/Podfile.lock b/frontend/appflowy_flutter/macos/Podfile.lock index b4a1a3d20d..30ee626f09 100644 --- a/frontend/appflowy_flutter/macos/Podfile.lock +++ b/frontend/appflowy_flutter/macos/Podfile.lock @@ -144,34 +144,34 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: - app_links: 10e0a0ab602ffaf34d142cd4862f29d34b303b2a - appflowy_backend: 865496343de667fc8c600e04b9fd05234e130cf9 - auto_updater_macos: 3e3462c418fe4e731917eacd8d28eef7af84086d - bitsdojo_window_macos: 44e3b8fe3dd463820e0321f6256c5b1c16bb6a00 - connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747 - desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898 - device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720 - file_selector_macos: cc3858c981fe6889f364731200d6232dac1d812d - flowy_infra_ui: 03301a39ad118771adbf051a664265c61c507f38 + app_links: 9028728e32c83a0831d9db8cf91c526d16cc5468 + appflowy_backend: 464aeb3e5c6966a41641a2111e5ead72ce2695f7 + auto_updater_macos: 3a42f1a06be6981f1a18be37e6e7bf86aa732118 + bitsdojo_window_macos: 7959fb0ca65a3ccda30095c181ecb856fae48ea9 + connectivity_plus: e74b9f74717d2d99d45751750e266e55912baeb5 + desktop_drop: e0b672a7d84c0a6cbc378595e82cdb15f2970a43 + device_info_plus: a56e6e74dbbd2bb92f2da12c64ddd4f67a749041 + file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31 + flowy_infra_ui: 8760ff42a789de40bf5007a5f176b454722a341e FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 HotKey: 400beb7caa29054ea8d864c96f5ba7e5b4852277 - hotkey_manager: c32bf0bfe8f934b7bc17ab4ad5c4c142960b023c - irondash_engine_context: da62996ee25616d2f01bbeb85dc115d813359478 - local_notifier: e9506bc66fc70311e8bc7291fb70f743c081e4ff - package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + hotkey_manager: b443f35f4d772162937aa73fd8995e579f8ac4e2 + irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba + local_notifier: ebf072651e35ae5e47280ad52e2707375cb2ae4e + package_info_plus: f0052d280d17aa382b932f399edf32507174e870 + path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda - screen_retriever_macos: 776e0fa5d42c6163d2bf772d22478df4b302b161 + screen_retriever_macos: 452e51764a9e1cdb74b3c541238795849f21557f Sentry: 1fe34e9c2cbba1e347623610d26db121dcb569f1 - sentry_flutter: a39c2a2d67d5e5b9cb0b94a4985c76dd5b3fc737 - share_plus: 1fa619de8392a4398bfaf176d441853922614e89 - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + sentry_flutter: e24b397f9a61fa5bbefd8279c3b2242ca86faa90 + share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc + shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 Sparkle: 5f8960a7a119aa7d45dacc0d5837017170bc5675 - sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d - super_native_extensions: 85efee3a7495b46b04befcfc86ed12069264ebf3 - url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 - webview_flutter_wkwebview: 0982481e3d9c78fd5c6f62a002fcd24fc791f1e4 - window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 + sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 + super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189 + url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673 + webview_flutter_wkwebview: 44d4dee7d7056d5ad185d25b38404436d56c547c + window_manager: 1d01fa7ac65a6e6f83b965471b1a7fdd3f06166c PODFILE CHECKSUM: 0532f3f001ca3110b8be345d6491fff690e95823 diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index bebb1779c6..6a2092876c 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -90,8 +90,8 @@ packages: dependency: "direct main" description: path: "." - ref: "2b8c3af" - resolved-ref: "2b8c3af54802f71cfb9156ea2e824bc57faa3ec7" + ref: ec7350d + resolved-ref: ec7350da7c298639c85e88229033da0c8aae8578 url: "https://github.com/AppFlowy-IO/appflowy-editor.git" source: git version: "5.1.0" diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 693e29a505..f78d776639 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -180,7 +180,7 @@ dependency_overrides: appflowy_editor: git: url: https://github.com/AppFlowy-IO/appflowy-editor.git - ref: "2b8c3af" + ref: "ec7350d" appflowy_editor_plugins: git: diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index 624ccecb4a..da50dc2504 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -259,7 +259,6 @@ "allSelected": "All selected" }, "stopTooltip": "Stop generating" - }, "trash": { "text": "Trash", @@ -2762,6 +2761,7 @@ "moreOptions": "More options", "collapse": "Collapse", "signInAgreement": "By clicking \"Continue\" above, you agreed to AppFlowy's", + "signInLocalAgreement": "By clicking \"Get Started\" above, you agreed to AppFlowy's", "and": "and", "termOfUse": "Terms", "privacyPolicy": "Privacy Policy",