diff --git a/frontend/appflowy_flutter/integration_test/shared/settings.dart b/frontend/appflowy_flutter/integration_test/shared/settings.dart index bfc5efedde..6deaa8b43e 100644 --- a/frontend/appflowy_flutter/integration_test/shared/settings.dart +++ b/frontend/appflowy_flutter/integration_test/shared/settings.dart @@ -9,7 +9,6 @@ import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart'; import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart'; import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra_ui/style_widget/text_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -86,7 +85,7 @@ extension AppFlowySettings on WidgetTester { final userNameFinder = find.descendant( of: find.byType(AccountUserProfile), - matching: find.byType(FlowyTextField), + matching: find.byType(TextField), ); await enterText(userNameFinder, name); await pumpAndSettle(); diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/home/shared/mobile_page_card.dart b/frontend/appflowy_flutter/lib/mobile/presentation/home/shared/mobile_page_card.dart index 87ce41d5b6..df7e2a1819 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/home/shared/mobile_page_card.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/home/shared/mobile_page_card.dart @@ -200,7 +200,9 @@ class MobileViewPage extends StatelessWidget { const WidgetSpan(child: HSpace(8.0)), ], TextSpan( - text: name, + text: name.orDefault( + LocaleKeys.menuAppHeader_defaultNewPageName.tr(), + ), style: Theme.of(context).textTheme.bodyMedium!.copyWith( fontSize: 16.0, fontWeight: FontWeight.w600, diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/invite_members_screen.dart b/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/invite_members_screen.dart index fa04e016a8..d4806decdc 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/invite_members_screen.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/invite_members_screen.dart @@ -108,31 +108,33 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { child: BlocConsumer( listener: _onListener, builder: (context, state) { - return Column( - children: [ - if (state.myRole.isOwner) ...[ - Container( - width: double.infinity, - padding: EdgeInsets.all(theme.spacing.xl), - child: const MInviteMemberByLink(), - ), - VSpace(theme.spacing.m), + return SingleChildScrollView( + child: Column( + children: [ + if (state.myRole.isOwner) ...[ + Container( + width: double.infinity, + padding: EdgeInsets.all(theme.spacing.xl), + child: const MInviteMemberByLink(), + ), + VSpace(theme.spacing.m), + ], + if (state.members.isNotEmpty) ...[ + const AFDivider(), + VSpace(theme.spacing.xl), + MobileMemberList( + members: state.members, + userProfile: userProfile, + myRole: state.myRole, + ), + ], + if (state.myRole.isMember) ...[ + Spacer(), + const _LeaveWorkspaceButton(), + ], + const VSpace(48), ], - if (state.members.isNotEmpty) ...[ - const AFDivider(), - VSpace(theme.spacing.xl), - MobileMemberList( - members: state.members, - userProfile: userProfile, - myRole: state.myRole, - ), - ], - if (state.myRole.isMember) ...[ - Spacer(), - const _LeaveWorkspaceButton(), - ], - const VSpace(48), - ], + ), ); }, ), diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/workspace_setting_group.dart b/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/workspace_setting_group.dart index fd981a4f2b..0bc7b9c3c5 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/workspace_setting_group.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/workspace_setting_group.dart @@ -1,6 +1,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/mobile/presentation/setting/widgets/mobile_setting_trailing.dart'; import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart'; +import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -18,14 +19,22 @@ class WorkspaceSettingGroup extends StatelessWidget { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - final currentWorkspace = state.currentWorkspace; + final currentWorkspace = state.workspaces.firstWhereOrNull( + (e) => e.workspaceId == state.currentWorkspace?.workspaceId, + ); + final memberCount = currentWorkspace?.memberCount; + String memberCountText = ''; + // if the member count is greater than 0, show the member count + if (memberCount != null && memberCount > 0) { + memberCountText = memberCount.toString(); + } return MobileSettingGroup( groupTitle: LocaleKeys.settings_appearance_members_label.tr(), settingItemList: [ MobileSettingItem( name: LocaleKeys.settings_appearance_members_label.tr(), trailing: MobileSettingTrailing( - text: currentWorkspace?.memberCount.toString() ?? '', + text: memberCountText, ), onTap: () { context.push(InviteMembersScreen.routeName); 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 9853f9c1bd..ca3f1a0db1 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 @@ -280,6 +280,7 @@ class _ChecklistItemState extends State { child: ChecklistCellTextfield( textController: textController, focusNode: textFieldFocusNode, + lineHeight: Platform.isWindows ? 1.2 : 1.1, onChanged: () { _debounceOnChanged.call(() { if (!isComposing) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/checklist_cell_textfield.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/checklist_cell_textfield.dart index 789a4adf46..2405247f6f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/checklist_cell_textfield.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/checklist_cell_textfield.dart @@ -46,6 +46,7 @@ class ChecklistCellTextfield extends StatelessWidget { horizontal: 2, ), this.onSubmitted, + this.lineHeight, }); final TextEditingController textController; @@ -53,13 +54,17 @@ class ChecklistCellTextfield extends StatelessWidget { final EdgeInsetsGeometry contentPadding; final VoidCallback? onSubmitted; final VoidCallback? onChanged; + final double? lineHeight; @override Widget build(BuildContext context) { + final textStyle = Theme.of(context).textTheme.bodyMedium; return TextField( controller: textController, focusNode: focusNode, - style: Theme.of(context).textTheme.bodyMedium, + style: textStyle?.copyWith( + height: lineHeight, + ), maxLines: null, decoration: InputDecoration( border: InputBorder.none, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/backtick_character_command.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/backtick_character_command.dart index ca26c5a263..9082144709 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/backtick_character_command.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/backtick_character_command.dart @@ -31,15 +31,22 @@ Future _convertBacktickToCodeBlock({ } // only active when the backtick is at the beginning of the line + final keyword = '``'; final plainText = delta.toPlainText(); - if (plainText != '``') { + if (!plainText.startsWith(keyword)) { return false; } final transaction = editorState.transaction; - transaction.insertNode( + final deltaWithoutKeyword = delta.compose(Delta()..delete(keyword.length)); + transaction.insertNodes( selection.end.path, - codeBlockNode(), + [ + codeBlockNode( + delta: deltaWithoutKeyword, + ), + if (node.children.isNotEmpty) ...node.children.map((e) => e.copyWith()), + ], ); transaction.deleteNode(node); transaction.afterSelection = Selection.collapsed( diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/shortcuts/custom_delete_command.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/shortcuts/custom_delete_command.dart index e0663c2bcf..ca33e39d2c 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/shortcuts/custom_delete_command.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/shortcuts/custom_delete_command.dart @@ -1,4 +1,5 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/simple_table/simple_table_block_component.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/simple_table/simple_table_cell_block_component.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/material.dart'; @@ -96,7 +97,13 @@ CommandShortcutEventHandler _deleteInNotCollapsedSelection = (editorState) { if (selection == null || selection.isCollapsed) { return KeyEventResult.ignored; } - editorState.deleteSelection(selection); + editorState.deleteSelection( + selection, + ignoreNodeTypes: [ + SimpleTableCellBlockKeys.type, + TableCellBlockKeys.type, + ], + ); return KeyEventResult.handled; }; diff --git a/frontend/appflowy_flutter/lib/user/application/password/password_http_service.dart b/frontend/appflowy_flutter/lib/user/application/password/password_http_service.dart index 5a386b4515..b50d24495d 100644 --- a/frontend/appflowy_flutter/lib/user/application/password/password_http_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/password/password_http_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:appflowy_backend/log.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/code.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_result/appflowy_result.dart'; import 'package:http/http.dart' as http; @@ -207,8 +208,15 @@ class PasswordHttpService { '${endpoint.name} request failed: ${response.statusCode}, $errorBody ', ); + ErrorCode errorCode = ErrorCode.Internal; + + if (response.statusCode == 422) { + errorCode = ErrorCode.NewPasswordTooWeak; + } + return FlowyResult.failure( FlowyError( + code: errorCode, msg: errorBody['msg'] ?? errorMessage, ), ); diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/continue_with/set_new_password.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/continue_with/set_new_password.dart index ecacad5903..5a0560e2de 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/continue_with/set_new_password.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/continue_with/set_new_password.dart @@ -5,6 +5,7 @@ import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/contin import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/continue_with/title_logo.dart'; import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/continue_with/verifying_button.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/code.pbenum.dart'; import 'package:appflowy_ui/appflowy_ui.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; @@ -60,9 +61,15 @@ class _SetNewPasswordWidgetState extends State { }); }, (error) { - newPasswordKey.currentState?.syncError( - errorText: error.msg, - ); + if (error.code == ErrorCode.NewPasswordTooWeak) { + newPasswordKey.currentState?.syncError( + errorText: LocaleKeys.signIn_passwordMustContain.tr(), + ); + } else { + newPasswordKey.currentState?.syncError( + errorText: error.msg, + ); + } }, ); } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/shared_widget.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/shared_widget.dart index 3cb5317984..6c41062ed1 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/shared_widget.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/shared_widget.dart @@ -208,16 +208,8 @@ class SpaceCancelOrConfirmButton extends StatelessWidget { borderRadius: BorderRadius.circular(8), ), ), - child: FlowyButton( - useIntrinsicWidth: true, - margin: - const EdgeInsets.symmetric(horizontal: 16.0, vertical: 9.0), - radius: BorderRadius.circular(8), - text: FlowyText.regular( - confirmButtonName, - lineHeight: 1.0, - color: Theme.of(context).colorScheme.onPrimary, - ), + child: AFFilledTextButton.destructive( + text: confirmButtonName, onTap: onConfirm, ), ), diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/password/change_password.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/password/change_password.dart index 876fc71350..22ff98cf5f 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/password/change_password.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/password/change_password.dart @@ -4,6 +4,7 @@ import 'package:appflowy/user/application/password/password_bloc.dart'; import 'package:appflowy/workspace/presentation/settings/pages/account/password/error_extensions.dart'; import 'package:appflowy/workspace/presentation/settings/pages/account/password/password_suffix_icon.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/code.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:appflowy_ui/appflowy_ui.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -359,6 +360,10 @@ class _ChangePasswordDialogContentState newPasswordTextFieldKey.currentState?.syncError( errorText: AFPasswordErrorExtension.getErrorMessage(error), ); + } else if (error.code == ErrorCode.NewPasswordTooWeak) { + newPasswordTextFieldKey.currentState?.syncError( + errorText: LocaleKeys.signIn_passwordMustContain.tr(), + ); } else { newPasswordTextFieldKey.currentState?.syncError( errorText: error.msg, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/password/setup_password.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/password/setup_password.dart index c70f1d96c8..16667d3d63 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/password/setup_password.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/password/setup_password.dart @@ -4,6 +4,7 @@ import 'package:appflowy/user/application/password/password_bloc.dart'; import 'package:appflowy/workspace/presentation/settings/pages/account/password/error_extensions.dart'; import 'package:appflowy/workspace/presentation/settings/pages/account/password/password_suffix_icon.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/code.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:appflowy_ui/appflowy_ui.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -291,6 +292,10 @@ class _SetupPasswordDialogContentState passwordTextFieldKey.currentState?.syncError( errorText: AFPasswordErrorExtension.getErrorMessage(error), ); + } else if (error.code == ErrorCode.NewPasswordTooWeak) { + passwordTextFieldKey.currentState?.syncError( + errorText: LocaleKeys.signIn_passwordMustContain.tr(), + ); } else { passwordTextFieldKey.currentState?.syncError( errorText: error.msg, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_shortcuts_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_shortcuts_view.dart index 0d3716c7dc..d381cf0f2b 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_shortcuts_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_shortcuts_view.dart @@ -17,6 +17,7 @@ import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/em import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart'; +import 'package:appflowy_ui/appflowy_ui.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme_extension.dart'; @@ -134,47 +135,9 @@ class _SearchBar extends StatelessWidget { @override Widget build(BuildContext context) { - return SizedBox( - height: 36, - child: FlowyTextField( - onChanged: onSearchChanged, - textStyle: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.w400, - ), - decoration: InputDecoration( - hintText: LocaleKeys.settings_shortcutsPage_searchHint.tr(), - counterText: '', - contentPadding: const EdgeInsets.symmetric( - vertical: 9, - horizontal: 16, - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).colorScheme.outline, - ), - borderRadius: Corners.s12Border, - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).colorScheme.primary, - ), - borderRadius: Corners.s12Border, - ), - errorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).colorScheme.error, - ), - borderRadius: Corners.s12Border, - ), - focusedErrorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).colorScheme.error, - ), - borderRadius: Corners.s12Border, - ), - ), - ), + return AFTextField( + onChanged: onSearchChanged, + hintText: LocaleKeys.settings_shortcutsPage_searchHint.tr(), ); } } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/settings_input_field.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/settings_input_field.dart index d5a81655a5..41e2c10cd1 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/settings_input_field.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/shared/settings_input_field.dart @@ -1,10 +1,11 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/workspace/presentation/settings/pages/account/password/password_suffix_icon.dart'; +import 'package:appflowy_ui/appflowy_ui.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/material.dart'; /// This is used to describe a settings input field /// @@ -104,36 +105,24 @@ class _SettingsInputFieldState extends State { ), if (widget.label?.isNotEmpty ?? false || widget.tooltip != null) const VSpace(8), - SizedBox( - height: 48, - child: FlowyTextField( - focusNode: focusNode, - hintText: widget.placeholder, - controller: controller, - autoFocus: false, - obscureText: obscureText, - isDense: false, - suffixIconConstraints: - BoxConstraints.tight(const Size(23 + 18, 24)), - suffixIcon: !widget.obscureText - ? null - : GestureDetector( - onTap: () => setState(() => obscureText = !obscureText), - child: Padding( - padding: const EdgeInsets.only(right: 18), - child: FlowySvg( - obscureText ? FlowySvgs.show_m : FlowySvgs.hide_m, - size: const Size(12, 15), - color: Theme.of(context).colorScheme.outline, - ), - ), - ), - onSubmitted: widget.onSave, - onChanged: (_) { - widget.onChanged?.call(controller.text); - setState(() {}); - }, - ), + AFTextField( + controller: controller, + focusNode: focusNode, + hintText: widget.placeholder, + obscureText: obscureText, + onSubmitted: widget.onSave, + onChanged: (_) { + widget.onChanged?.call(controller.text); + setState(() {}); + }, + suffixIconBuilder: (context, isObscured) => widget.obscureText + ? PasswordSuffixIcon( + isObscured: isObscured, + onTap: () { + setState(() => obscureText = !obscureText); + }, + ) + : null, ), if (!widget.hideActions && ((widget.value == null && controller.text.isNotEmpty) || diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/inivitation/m_invite_member_by_link.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/inivitation/m_invite_member_by_link.dart index 41f1363efe..6ac78cadd4 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/inivitation/m_invite_member_by_link.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/inivitation/m_invite_member_by_link.dart @@ -141,11 +141,11 @@ class _CopyLinkButton extends StatelessWidget { ); showToastNotification( - message: LocaleKeys.document_inlineLink_copyLink.tr(), + message: LocaleKeys.shareAction_copyLinkSuccess.tr(), ); } else { showToastNotification( - message: 'You haven\'t generated an invite link yet.', + message: LocaleKeys.settings_appearance_members_noInviteLink.tr(), type: ToastificationType.error, ); } diff --git a/frontend/appflowy_flutter/packages/appflowy_ui/lib/src/component/textfield/textfield.dart b/frontend/appflowy_flutter/packages/appflowy_ui/lib/src/component/textfield/textfield.dart index f444026eb1..413891aea0 100644 --- a/frontend/appflowy_flutter/packages/appflowy_ui/lib/src/component/textfield/textfield.dart +++ b/frontend/appflowy_flutter/packages/appflowy_ui/lib/src/component/textfield/textfield.dart @@ -30,6 +30,7 @@ class AFTextField extends StatefulWidget { this.suffixIconConstraints, this.size = AFTextFieldSize.l, this.groupId = EditableText, + this.focusNode, }); /// The hint text to display when the text field is empty. @@ -65,7 +66,7 @@ class AFTextField extends StatefulWidget { final bool obscureText; /// The trailing widget to display. - final Widget Function(BuildContext context, bool isObscured)? + final Widget? Function(BuildContext context, bool isObscured)? suffixIconBuilder; /// The size of the suffix icon. @@ -74,6 +75,9 @@ class AFTextField extends StatefulWidget { /// The group ID for the text field. final Object groupId; + /// The focus node for the text field. + final FocusNode? focusNode; + @override State createState() => _AFTextFieldState(); } @@ -123,6 +127,7 @@ class _AFTextFieldState extends AFTextFieldState { Widget child = TextField( groupId: widget.groupId, + focusNode: widget.focusNode, controller: effectiveController, keyboardType: widget.keyboardType, style: theme.textStyle.body.standard( diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index e887f0d645..eda3de1f56 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -98,11 +98,11 @@ packages: dependency: "direct main" description: path: "." - ref: "680222f" - resolved-ref: "680222f503f90d07c08c99c42764f9b08fd0f46c" + ref: "6d5f6a7755703d8ae065e773d863a4b880073d26" + resolved-ref: "6d5f6a7755703d8ae065e773d863a4b880073d26" url: "https://github.com/AppFlowy-IO/appflowy-editor.git" source: git - version: "5.1.0" + version: "5.2.0" appflowy_editor_plugins: dependency: "direct main" description: diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index eab0d7d004..8c63be609d 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -187,7 +187,7 @@ dependency_overrides: appflowy_editor: git: url: https://github.com/AppFlowy-IO/appflowy-editor.git - ref: "680222f" + ref: "6d5f6a7755703d8ae065e773d863a4b880073d26" appflowy_editor_plugins: git: diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index fde9bf9d39..b874d8cb24 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -48,6 +48,7 @@ "createAccount": "Create account", "repeatPasswordEmptyError": "Repeat password can't be empty", "unmatchedPasswordError": "Repeat password is not the same as password", + "passwordMustContain": "Password must contain at least one letter, one number, and one symbol.", "syncPromptMessage": "Syncing the data might take a while. Please don't close this page", "or": "or", "signInWithGoogle": "Continue with Google", diff --git a/frontend/rust-lib/flowy-error/src/code.rs b/frontend/rust-lib/flowy-error/src/code.rs index b64da1c35f..de6faa3c4d 100644 --- a/frontend/rust-lib/flowy-error/src/code.rs +++ b/frontend/rust-lib/flowy-error/src/code.rs @@ -386,6 +386,18 @@ pub enum ErrorCode { #[error("Reference resource is not available")] WeakRefDrop = 132, + + #[error("New password is too weak")] + NewPasswordTooWeak = 133, + + #[error("Invalid new password")] + InvalidNewPassword = 134, + + #[error("New password is too long")] + NewPasswordTooLong = 135, + + #[error("New password is too short")] + NewPasswordTooShort = 136, } impl ErrorCode {