diff --git a/frontend/appflowy_flutter/integration_test/desktop/cloud/uncategorized/appflowy_cloud_auth_test.dart b/frontend/appflowy_flutter/integration_test/desktop/cloud/uncategorized/appflowy_cloud_auth_test.dart index fd65c29927..c48ce5d264 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/cloud/uncategorized/appflowy_cloud_auth_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/cloud/uncategorized/appflowy_cloud_auth_test.dart @@ -39,7 +39,7 @@ void main() { ); await tester.tapButton(find.byType(AccountSignInOutButton)); - tester.expectToSeeText(LocaleKeys.button_ok.tr()); + tester.expectToSeeText(LocaleKeys.button_yes.tr()); await tester.tapButtonWithName(LocaleKeys.button_ok.tr()); // Go to the sign in page again diff --git a/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart b/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart index 88f9634afd..89451ba8b6 100644 --- a/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart +++ b/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart @@ -28,8 +28,8 @@ extension AppFlowyAuthTest on WidgetTester { await tapButton(find.byType(AccountSignInOutButton)); - expectToSeeText(LocaleKeys.button_ok.tr()); - await tapButtonWithName(LocaleKeys.button_ok.tr()); + expectToSeeText(LocaleKeys.button_yes.tr()); + await tapButtonWithName(LocaleKeys.button_yes.tr()); } Future tapSignInAsGuest() async { diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/add_members_screen.dart b/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/add_members_screen.dart index 729993271f..68d603ab60 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/add_members_screen.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/setting/workspace/add_members_screen.dart @@ -121,41 +121,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { ); } - // Widget _buildInviteMemberArea(BuildContext context) { - // return Column( - // children: [ - // TextFormField( - // autofocus: true, - // controller: emailController, - // keyboardType: TextInputType.text, - // decoration: InputDecoration( - // hintText: LocaleKeys.settings_appearance_members_inviteHint.tr(), - // ), - // ), - // const VSpace(16), - // if (exceededLimit) ...[ - // FlowyText.regular( - // LocaleKeys.settings_appearance_members_inviteFailedMemberLimitMobile - // .tr(), - // fontSize: 14.0, - // maxLines: 3, - // color: Theme.of(context).colorScheme.error, - // ), - // const VSpace(16), - // ], - // SizedBox( - // width: double.infinity, - // child: ElevatedButton( - // onPressed: () => _inviteMember(context), - // child: Text( - // LocaleKeys.settings_appearance_members_sendInvite.tr(), - // ), - // ), - // ), - // ], - // ); - // } - Widget _buildError(BuildContext context) { return Center( child: Padding( @@ -194,9 +159,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { final actionType = actionResult.actionType; final result = actionResult.result; - // get keyboard height - final keyboardHeight = MediaQuery.of(context).viewInsets.bottom; - // only show the result dialog when the action is WorkspaceMemberActionType.add if (actionType == WorkspaceMemberActionType.addByEmail) { result.fold( @@ -204,7 +166,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { showToastNotification( message: LocaleKeys.settings_appearance_members_addMemberSuccess.tr(), - bottomPadding: keyboardHeight, ); }, (f) { @@ -219,7 +180,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { }); showToastNotification( type: ToastificationType.error, - bottomPadding: keyboardHeight, message: message, ); }, @@ -230,7 +190,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { showToastNotification( message: LocaleKeys.settings_appearance_members_inviteMemberSuccess.tr(), - bottomPadding: keyboardHeight, ); }, (f) { @@ -247,7 +206,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { showToastNotification( type: ToastificationType.error, message: message, - bottomPadding: keyboardHeight, ); }, ); @@ -258,7 +216,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { message: LocaleKeys .settings_appearance_members_removeFromWorkspaceSuccess .tr(), - bottomPadding: keyboardHeight, ); }, (f) { @@ -267,48 +224,65 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { message: LocaleKeys .settings_appearance_members_removeFromWorkspaceFailed .tr(), - bottomPadding: keyboardHeight, ); }, ); } else if (actionType == WorkspaceMemberActionType.generateInviteLink) { result.fold( - (s) { + (s) async { showToastNotification( - message: 'Invite link generated successfully', + message: LocaleKeys + .settings_appearance_members_generatedLinkSuccessfully + .tr(), ); // copy the invite link to the clipboard final inviteLink = state.inviteLink; if (inviteLink != null) { - getIt().setPlainText(inviteLink); + await getIt().setPlainText(inviteLink); + showToastNotification( + message: LocaleKeys.shareAction_copyLinkSuccess.tr(), + ); } }, (f) { Log.error('generate invite link failed: $f'); showToastNotification( - message: 'Failed to generate invite link', + type: ToastificationType.error, + message: + LocaleKeys.settings_appearance_members_generatedLinkFailed.tr(), + ); + }, + ); + } else if (actionType == WorkspaceMemberActionType.resetInviteLink) { + result.fold( + (s) async { + showToastNotification( + message: LocaleKeys + .settings_appearance_members_resetLinkSuccessfully + .tr(), + ); + + // copy the invite link to the clipboard + final inviteLink = state.inviteLink; + if (inviteLink != null) { + await getIt().setPlainText(inviteLink); + showToastNotification( + message: LocaleKeys.shareAction_copyLinkSuccess.tr(), + ); + } + }, + (f) { + Log.error('generate invite link failed: $f'); + showToastNotification( + type: ToastificationType.error, + message: + LocaleKeys.settings_appearance_members_resetLinkFailed.tr(), ); }, ); } } - - // void _inviteMember(BuildContext context) { - // final email = emailController.text; - // if (!isEmail(email)) { - // showToastNotification( - // type: ToastificationType.error, - // message: LocaleKeys.settings_appearance_members_emailInvalidError.tr(), - // ); - // return; - // } - // context - // .read() - // .add(WorkspaceMemberEvent.inviteWorkspaceMemberByEmail(email)); - // // clear the email field after inviting - // emailController.clear(); - // } } class _LeaveWorkspaceButton extends StatelessWidget { 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 77d21697d3..fa04e016a8 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 @@ -179,9 +179,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { final actionType = actionResult.actionType; final result = actionResult.result; - // get keyboard height - final keyboardHeight = MediaQuery.of(context).viewInsets.bottom; - // only show the result dialog when the action is WorkspaceMemberActionType.add if (actionType == WorkspaceMemberActionType.addByEmail) { result.fold( @@ -189,7 +186,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { showToastNotification( message: LocaleKeys.settings_appearance_members_addMemberSuccess.tr(), - bottomPadding: keyboardHeight, ); }, (f) { @@ -204,7 +200,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { }); showToastNotification( type: ToastificationType.error, - bottomPadding: keyboardHeight, message: message, ); }, @@ -215,7 +210,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { showToastNotification( message: LocaleKeys.settings_appearance_members_inviteMemberSuccess.tr(), - bottomPadding: keyboardHeight, ); }, (f) { @@ -229,10 +223,10 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { setState(() { exceededLimit = f.code == ErrorCode.WorkspaceMemberLimitExceeded; }); + showToastNotification( type: ToastificationType.error, message: message, - bottomPadding: keyboardHeight, ); }, ); @@ -243,7 +237,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { message: LocaleKeys .settings_appearance_members_removeFromWorkspaceSuccess .tr(), - bottomPadding: keyboardHeight, ); }, (f) { @@ -252,7 +245,6 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { message: LocaleKeys .settings_appearance_members_removeFromWorkspaceFailed .tr(), - bottomPadding: keyboardHeight, ); }, ); @@ -260,20 +252,53 @@ class _InviteMemberPageState extends State<_InviteMemberPage> { result.fold( (s) { showToastNotification( - message: 'Invite link generated successfully', + message: LocaleKeys + .settings_appearance_members_generatedLinkSuccessfully + .tr(), ); // copy the invite link to the clipboard final inviteLink = state.inviteLink; if (inviteLink != null) { getIt().setPlainText(inviteLink); + showToastNotification( + message: LocaleKeys.shareAction_copyLinkSuccess.tr(), + ); } }, (f) { Log.error('generate invite link failed: $f'); showToastNotification( type: ToastificationType.error, - message: 'Failed to generate invite link', + message: + LocaleKeys.settings_appearance_members_generatedLinkFailed.tr(), + ); + }, + ); + } else if (actionType == WorkspaceMemberActionType.resetInviteLink) { + result.fold( + (s) { + showToastNotification( + message: LocaleKeys + .settings_appearance_members_resetLinkSuccessfully + .tr(), + ); + + // copy the invite link to the clipboard + final inviteLink = state.inviteLink; + if (inviteLink != null) { + getIt().setPlainText(inviteLink); + showToastNotification( + message: LocaleKeys.shareAction_copyLinkSuccess.tr(), + ); + } + }, + (f) { + Log.error('generate invite link failed: $f'); + showToastNotification( + type: ToastificationType.error, + message: + LocaleKeys.settings_appearance_members_resetLinkFailed.tr(), ); }, ); diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/continue_with/continue_with_magic_link_or_passcode_page.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/continue_with/continue_with_magic_link_or_passcode_page.dart index 7a87c3efd1..d747fefc96 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/continue_with/continue_with_magic_link_or_passcode_page.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/widgets/continue_with/continue_with_magic_link_or_passcode_page.dart @@ -130,7 +130,7 @@ class _ContinueWithMagicLinkOrPasscodePageState isSubmitting ? const VerifyingButton() : ContinueWithButton( - text: LocaleKeys.signIn_continueToSignIn.tr(), + text: LocaleKeys.signIn_continueWithLoginCode.tr(), onTap: () { final passcode = passcodeController.text; if (passcode.isEmpty) { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/account_sign_in_out.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/account_sign_in_out.dart index 90d60fd494..b647010b69 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/account_sign_in_out.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/account_sign_in_out.dart @@ -76,10 +76,11 @@ class AccountSignInOutButton extends StatelessWidget { } void _showLogoutDialog(BuildContext context) { - showConfirmDialog( + showCancelAndConfirmDialog( context: context, title: LocaleKeys.settings_accountPage_login_logoutLabel.tr(), description: LocaleKeys.settings_menu_logoutPrompt.tr(), + confirmLabel: LocaleKeys.button_yes.tr(), onConfirm: () async { await getIt().signOut(); onAction(); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/inivitation/inivite_member_by_link.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/inivitation/inivite_member_by_link.dart index b6d46316fe..6a48e12215 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/inivitation/inivite_member_by_link.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/inivitation/inivite_member_by_link.dart @@ -85,7 +85,28 @@ class _Description extends StatelessWidget { } Future _onGenerateInviteLink(BuildContext context) async { - final inviteLink = context.read().state.inviteLink; + final state = context.read().state; + final inviteLink = state.inviteLink; + + // check the current workspace member count, if it exceed the limit, show a upgrade dialog. + // prevent hard code here, because the member count may exceed the limit after the invite link is generated. + if (inviteLink == null && state.members.length >= 3) { + await showConfirmDialog( + context: context, + title: + LocaleKeys.settings_appearance_members_inviteFailedDialogTitle.tr(), + description: + LocaleKeys.settings_appearance_members_inviteFailedMemberLimit.tr(), + confirmLabel: LocaleKeys + .settings_appearance_members_memberLimitExceededUpgrade + .tr(), + onConfirm: () => context + .read() + .add(const WorkspaceMemberEvent.upgradePlan()), + ); + return; + } + if (inviteLink != null) { // show a dialog to confirm if the user wants to copy the link to the clipboard await showConfirmDialog( @@ -120,9 +141,16 @@ class _Description extends StatelessWidget { } } -class _CopyLinkButton extends StatelessWidget { +class _CopyLinkButton extends StatefulWidget { const _CopyLinkButton(); + @override + State<_CopyLinkButton> createState() => _CopyLinkButtonState(); +} + +class _CopyLinkButtonState extends State<_CopyLinkButton> { + ToastificationItem? toastificationItem; + @override Widget build(BuildContext context) { final theme = AppFlowyTheme.of(context); @@ -135,16 +163,42 @@ class _CopyLinkButton extends StatelessWidget { horizontal: theme.spacing.l, vertical: theme.spacing.s, ), - onTap: () { - final link = context.read().state.inviteLink; + onTap: () async { + final state = context.read().state; + // check the current workspace member count, if it exceed the limit, show a upgrade dialog. + // prevent hard code here, because the member count may exceed the limit after the invite link is generated. + if (state.members.length >= 3) { + await showConfirmDialog( + context: context, + title: LocaleKeys + .settings_appearance_members_inviteFailedDialogTitle + .tr(), + description: LocaleKeys + .settings_appearance_members_inviteFailedMemberLimit + .tr(), + confirmLabel: LocaleKeys + .settings_appearance_members_memberLimitExceededUpgrade + .tr(), + onConfirm: () => context + .read() + .add(const WorkspaceMemberEvent.upgradePlan()), + ); + return; + } + + final link = state.inviteLink; if (link != null) { - getIt().setData( + await getIt().setData( ClipboardServiceData( plainText: link, ), ); - showToastNotification( + if (toastificationItem != null) { + toastification.dismiss(toastificationItem!); + } + + toastificationItem = showToastNotification( message: LocaleKeys.shareAction_copyLinkSuccess.tr(), ); } else { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/workspace_member_bloc.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/workspace_member_bloc.dart index 8f006ce09b..c9176edfd9 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/workspace_member_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/workspace_member_bloc.dart @@ -239,13 +239,17 @@ class WorkspaceMemberBloc String link, ) async {} - Future _onGenerateInviteLink(Emitter emit) async { + Future _onGenerateInviteLink( + Emitter emit, + ) async { final workspaceId = _workspaceId.value; if (workspaceId == null) { Log.error('Failed to generate invite link: workspaceId is null'); return; } + final resetInviteLink = state.inviteLink != null; + final result = await _memberHttpService?.generateInviteCode( workspaceId: workspaceId, ); @@ -257,7 +261,9 @@ class WorkspaceMemberBloc state.copyWith( inviteLink: inviteLink, actionResult: WorkspaceMemberActionResult( - actionType: WorkspaceMemberActionType.generateInviteLink, + actionType: resetInviteLink + ? WorkspaceMemberActionType.resetInviteLink + : WorkspaceMemberActionType.generateInviteLink, result: result, ), ), @@ -268,7 +274,9 @@ class WorkspaceMemberBloc emit( state.copyWith( actionResult: WorkspaceMemberActionResult( - actionType: WorkspaceMemberActionType.generateInviteLink, + actionType: resetInviteLink + ? WorkspaceMemberActionType.resetInviteLink + : WorkspaceMemberActionType.generateInviteLink, result: result, ), ), @@ -359,7 +367,9 @@ class WorkspaceMemberBloc _memberHttpService?.getInviteCode(workspaceId: workspaceId).fold( (s) async { final inviteLink = await _buildInviteLink(inviteCode: s); - add(WorkspaceMemberEvent.updateInviteLink(inviteLink)); + if (!isClosed) { + add(WorkspaceMemberEvent.updateInviteLink(inviteLink)); + } }, (e) => Log.info('Failed to get invite code: ${e.msg}', e), ), @@ -472,6 +482,7 @@ enum WorkspaceMemberActionType { inviteByEmail, inviteByLink, generateInviteLink, + resetInviteLink, // this event will add the member without sending an invitation addByEmail, removeByEmail, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/workspace_member_page.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/workspace_member_page.dart index c297a87307..348575d1ab 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/workspace_member_page.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/members/workspace_member_page.dart @@ -252,27 +252,70 @@ class WorkspaceMembersPage extends StatelessWidget { .settings_appearance_members_inviteFailedDialogTitle .tr(), description: message, - confirmLabel: LocaleKeys.button_ok.tr(), + confirmLabel: LocaleKeys + .settings_appearance_members_memberLimitExceededUpgrade + .tr(), + onConfirm: () => context + .read() + .add(const WorkspaceMemberEvent.upgradePlan()), ); }, ); } else if (actionType == WorkspaceMemberActionType.generateInviteLink) { result.fold( - (s) { + (s) async { showToastNotification( - message: 'Invite link generated successfully', + message: LocaleKeys + .settings_appearance_members_generatedLinkSuccessfully + .tr(), ); // copy the invite link to the clipboard final inviteLink = state.inviteLink; if (inviteLink != null) { - getIt().setPlainText(inviteLink); + await getIt().setPlainText(inviteLink); + Future.delayed(const Duration(milliseconds: 200), () { + showToastNotification( + message: LocaleKeys.shareAction_copyLinkSuccess.tr(), + ); + }); } }, (f) { Log.error('generate invite link failed: $f'); showToastNotification( - message: 'Failed to generate invite link', + type: ToastificationType.error, + message: + LocaleKeys.settings_appearance_members_generatedLinkFailed.tr(), + ); + }, + ); + } else if (actionType == WorkspaceMemberActionType.resetInviteLink) { + result.fold( + (s) async { + showToastNotification( + message: LocaleKeys + .settings_appearance_members_resetLinkSuccessfully + .tr(), + ); + + // copy the invite link to the clipboard + final inviteLink = state.inviteLink; + if (inviteLink != null) { + await getIt().setPlainText(inviteLink); + Future.delayed(const Duration(milliseconds: 200), () { + showToastNotification( + message: LocaleKeys.shareAction_copyLinkSuccess.tr(), + ); + }); + } + }, + (f) { + Log.error('generate invite link failed: $f'); + showToastNotification( + type: ToastificationType.error, + message: + LocaleKeys.settings_appearance_members_resetLinkFailed.tr(), ); }, ); @@ -391,6 +434,8 @@ class _MemberItem extends StatelessWidget { style: theme.textStyle.body.enhanced( color: theme.textColorScheme.primary, ), + maxLines: 1, + overflow: TextOverflow.ellipsis, ), Text( _formatJoinedDate(member.joinedAt.toInt()), @@ -481,20 +526,18 @@ class _MemberMoreActionList extends StatelessWidget { onSelected: (action, controller) { switch (action.inner) { case _MemberMoreAction.delete: - showDialog( + showCancelAndConfirmDialog( context: context, - builder: (_) => NavigatorOkCancelDialog( - title: LocaleKeys.settings_appearance_members_removeMember.tr(), - message: LocaleKeys - .settings_appearance_members_areYouSureToRemoveMember - .tr(), - onOkPressed: () => context.read().add( - WorkspaceMemberEvent.removeWorkspaceMemberByEmail( - action.member.email, - ), + title: LocaleKeys.settings_appearance_members_removeMember.tr(), + description: LocaleKeys + .settings_appearance_members_areYouSureToRemoveMember + .tr(), + confirmLabel: LocaleKeys.button_yes.tr(), + onConfirm: () => context.read().add( + WorkspaceMemberEvent.removeWorkspaceMemberByEmail( + action.member.email, ), - okTitle: LocaleKeys.button_yes.tr(), - ), + ), ); break; } diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index d7ecc61450..04af03d6f8 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -77,6 +77,7 @@ "temporaryVerificationLinkSent": "A temporary verification link has been sent.\nPlease check your inbox at", "temporaryVerificationCodeSent": "A temporary verification code has been sent.\nPlease check your inbox at", "continueToSignIn": "Continue to sign in", + "continueWithLoginCode": "Continue with login code", "backToLogin": "Back to login", "enterCode": "Enter code", "enterCodeManually": "Enter code manually", @@ -563,7 +564,7 @@ "description": "This change will apply to all the published pages live on this namespace", "tooltip": "We reserve the rights to remove any inappropriate namespaces", "updateExistingNamespace": "Update existing namespace", - "upgradeToPro": "Upgrade to Pro Plan to set a homepage", + "upgradeToPro": "Upgrade to Pro Plan to claim a custom namespace", "redirectToPayment": "Redirecting to payment page...", "onlyWorkspaceOwnerCanSetHomePage": "Only the workspace owner can set a homepage", "pleaseAskOwnerToSetHomePage": "Please ask the workspace owner to upgrade to Pro Plan" @@ -1156,8 +1157,8 @@ "files": "Files", "notifications": "Notifications", "open": "Open Settings", - "logout": "Logout", - "logoutPrompt": "Are you sure you want to logout?", + "logout": "Log out", + "logoutPrompt": "Are you sure you want to log out?", "selfEncryptionLogoutPrompt": "Are you sure you want to log out? Please ensure you have copied the encryption secret", "syncSetting": "Sync Setting", "cloudSettings": "Cloud Settings", @@ -1353,8 +1354,8 @@ "one": "{} member", "other": "{} members" }, - "inviteFailedDialogTitle": "Failed to send invite", - "inviteFailedMemberLimit": "Member limit has been reached, please upgrade to invite more members.", + "inviteFailedDialogTitle": "Upgrade to Pro Plan", + "inviteFailedMemberLimit": "This workspace has reached the free limit. Please upgrade to Pro to unlock more members.", "inviteFailedMemberLimitMobile": "Your workspace has reached the member limit.", "memberLimitExceeded": "Member limit reached, to invite more members, please ", "memberLimitExceededUpgrade": "upgrade", @@ -1375,7 +1376,7 @@ "inviteMemberByEmail": "Invite member by email", "inviteMemberHintText": "Invite by email", "resetInviteLink": "Reset the invite link?", - "resetInviteLinkDescription": "Resetting will deactivate the current link for all space members and generate a new one. The old link will no longer be available.", + "resetInviteLinkDescription": "Resetting will deactivate the current link for all space members and generate a new one. The old link will no longer valid.", "adminPanel": "Admin Panel", "reset": "Reset", "resetInviteLinkSuccess": "Invite link reset successfully", @@ -1384,7 +1385,11 @@ "memberPageDescription1": "Access the", "memberPageDescription2": "for guest and advanced user management.", "noInviteLink": "You haven't generated an invite link yet.", - "copyLink": "Copy link" + "copyLink": "Copy link", + "generatedLinkSuccessfully": "Generated link successfully", + "generatedLinkFailed": "Failed to generate link", + "resetLinkSuccessfully": "Reset link successfully", + "resetLinkFailed": "Failed to reset link" } }, "files": { @@ -1433,7 +1438,7 @@ "tooltipSelectIcon": "Select icon", "selectAnIcon": "Select an icon", "pleaseInputYourOpenAIKey": "please input your AI key", - "clickToLogout": "Click to logout the current user" + "clickToLogout": "Click to log out the current user" }, "mobile": { "personalInfo": "Personal Information",