diff --git a/src/devhub/entity/post/PostEditor.jsx b/src/devhub/entity/post/PostEditor.jsx index a95772b4f..fb838cf72 100644 --- a/src/devhub/entity/post/PostEditor.jsx +++ b/src/devhub/entity/post/PostEditor.jsx @@ -1,3 +1,27 @@ +initState({ + seekingFunding: props.seekingFunding ?? false, + author_id: context.accountId, + // Should be a list of objects with field "name". + labels, + // Should be a list of labels as strings. + // Both of the label structures should be modified together. + labelStrings, + postType, + name: props.name ?? "", + description: + (props.postType === "Solution" + ? cleanDescription(props.description) + : props.description) ?? "", + amount: props.amount ?? "0", + token: props.token ?? "USDT", + supervisor: props.supervisor ?? "neardevdao.near", + githubLink: props.githubLink ?? "", + warning: "", + draftStateApplied: false, + mentionInput: "", // text next to @ tag + mentionsArray: [], // all the mentions in the description +}); + /* INCLUDE: "core/lib/autocomplete" */ const autocompleteEnabled = true; @@ -10,23 +34,46 @@ const AutoComplete = styled.div` `; function textareaInputHandler(value) { - const showAccountAutocomplete = /@[\w][^\s]*$/.test(value); + const words = value.split(/\s+/); + const allMentiones = words + .filter((word) => word.startsWith("@")) + .map((mention) => mention.slice(1)); + const newMentiones = allMentiones.filter( + (item) => !state.mentionsArray.includes(item) + ); + State.update((lastKnownState) => ({ ...lastKnownState, text: value, - showAccountAutocomplete, + showAccountAutocomplete: newMentiones?.length > 0, + mentionsArray: allMentiones, + mentionInput: newMentiones?.[0] ?? "", })); } function autoCompleteAccountId(id) { - let description = state.description.replace(/[\s]{0,1}@[^\s]*$/, ""); - description = `${description} @${id}`.trim() + " "; + // to make sure we update the @ at correct index + let currentIndex = 0; + const updatedDescription = state.description.replace( + /(?:^|\s)(@[^\s]*)/g, + (match) => { + if (currentIndex === state.mentionsArray.indexOf(state.mentionInput)) { + currentIndex++; + return ` @${id}`; + } else { + currentIndex++; + return match; + } + } + ); State.update((lastKnownState) => ({ ...lastKnownState, - description, + handler: "autocompleteSelected", + description: updatedDescription, showAccountAutocomplete: false, })); } + /* END_INCLUDE: "core/lib/autocomplete" */ const postType = props.postType ?? "Sponsorship"; @@ -49,28 +96,6 @@ const cleanDescription = (description) => { ); }; -initState({ - seekingFunding: props.seekingFunding ?? false, - author_id: context.accountId, - // Should be a list of objects with field "name". - labels, - // Should be a list of labels as strings. - // Both of the label structures should be modified together. - labelStrings, - postType, - name: props.name ?? "", - description: - (props.postType === "Solution" - ? cleanDescription(props.description) - : props.description) ?? "", - amount: props.amount ?? "0", - token: props.token ?? "USDT", - supervisor: props.supervisor ?? "neardevdao.near", - githubLink: props.githubLink ?? "", - warning: "", - draftStateApplied: false, -}); - if (!state.draftStateApplied && props.draftState) { State.update({ ...props.draftState, draftStateApplied: true }); } @@ -391,7 +416,7 @@ const callDescriptionDiv = () => { State.update({ showAccountAutocomplete: false }), }} diff --git a/src/devhub/page/create.jsx b/src/devhub/page/create.jsx index 65103dec9..9b91c1a41 100644 --- a/src/devhub/page/create.jsx +++ b/src/devhub/page/create.jsx @@ -1,5 +1,3 @@ -/* INCLUDE: "core/lib/autocomplete" */ - State.init({ seekingFunding: false, author_id: context.accountId, @@ -21,6 +19,8 @@ State.init({ mentionsArray: [], // all the mentions in the description }); +/* INCLUDE: "core/lib/autocomplete" */ + const autocompleteEnabled = true; const AutoComplete = styled.div`