Add Channel Mention selection ability #7151
2 changed files with 32 additions and 20 deletions
|
@ -119,7 +119,7 @@ export default function ChannelMentionSuggestions(props: Props) {
|
||||||
comboboxInputRef.current.focus();
|
comboboxInputRef.current.focus();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (keyCode === KEYCODES.TAB) {
|
if ((isRefFocused(comboboxInputRef) || isRefFocused(inputRef)) && keyCode === KEYCODES.TAB) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const activeValue = activeElement && activeElement.getAttribute('value');
|
const activeValue = activeElement && activeElement.getAttribute('value');
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ export default function ChannelMentionSuggestions(props: Props) {
|
||||||
handleSelect(mentionTerm);
|
handleSelect(mentionTerm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inputRef.current.focus();
|
if (isRefFocused(comboboxInputRef)) inputRef.current.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ export default function ChannelMentionSuggestions(props: Props) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return isRefFocused(inputRef) || isRefFocused(comboboxInputRef) ? (
|
||||||
<Form onSubmit={() => handleSelect(mentionTerm)}>
|
<Form onSubmit={() => handleSelect(mentionTerm)}>
|
||||||
<Combobox className="channel-mention" onSelect={handleSelect}>
|
<Combobox className="channel-mention" onSelect={handleSelect}>
|
||||||
<ComboboxInput ref={comboboxInputRef} className="channel-mention__input--none" value={mentionTerm} />
|
<ComboboxInput ref={comboboxInputRef} className="channel-mention__input--none" value={mentionTerm} />
|
||||||
|
@ -216,5 +216,5 @@ export default function ChannelMentionSuggestions(props: Props) {
|
||||||
)}
|
)}
|
||||||
</Combobox>
|
</Combobox>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
) : null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,8 @@ export function CommentCreate(props: Props) {
|
||||||
fetchComment,
|
fetchComment,
|
||||||
} = props;
|
} = props;
|
||||||
const formFieldRef: ElementRef<any> = React.useRef();
|
const formFieldRef: ElementRef<any> = React.useRef();
|
||||||
|
const formFieldInputRef = formFieldRef && formFieldRef.current && formFieldRef.current.input;
|
||||||
|
const selectionIndex = formFieldInputRef && formFieldInputRef.current.selectionStart;
|
||||||
const buttonRef: ElementRef<any> = React.useRef();
|
const buttonRef: ElementRef<any> = React.useRef();
|
||||||
const {
|
const {
|
||||||
push,
|
push,
|
||||||
|
@ -97,15 +99,25 @@ export function CommentCreate(props: Props) {
|
||||||
const [isReviewingSupportComment, setIsReviewingSupportComment] = React.useState();
|
const [isReviewingSupportComment, setIsReviewingSupportComment] = React.useState();
|
||||||
const [tipAmount, setTipAmount] = React.useState(1);
|
const [tipAmount, setTipAmount] = React.useState(1);
|
||||||
const [commentValue, setCommentValue] = React.useState('');
|
const [commentValue, setCommentValue] = React.useState('');
|
||||||
const [channelMention, setChannelMention] = React.useState('');
|
|
||||||
const [advancedEditor, setAdvancedEditor] = usePersistedState('comment-editor-mode', false);
|
const [advancedEditor, setAdvancedEditor] = usePersistedState('comment-editor-mode', false);
|
||||||
const [activeTab, setActiveTab] = React.useState('');
|
const [activeTab, setActiveTab] = React.useState('');
|
||||||
const [tipError, setTipError] = React.useState();
|
const [tipError, setTipError] = React.useState();
|
||||||
const [deletedComment, setDeletedComment] = React.useState(false);
|
const [deletedComment, setDeletedComment] = React.useState(false);
|
||||||
const [shouldDisableReviewButton, setShouldDisableReviewButton] = React.useState();
|
const [shouldDisableReviewButton, setShouldDisableReviewButton] = React.useState();
|
||||||
|
|
||||||
const commentWords = commentValue ? commentValue && commentValue.split(' ') : [];
|
const selectedMentionIndex =
|
||||||
const lastCommentWord = commentWords && commentWords[commentWords.length - 1];
|
commentValue.indexOf('@', selectionIndex) === selectionIndex
|
||||||
|
? commentValue.indexOf('@', selectionIndex)
|
||||||
|
: commentValue.lastIndexOf('@', selectionIndex);
|
||||||
|
const mentionLengthIndex =
|
||||||
|
commentValue.indexOf(' ', selectedMentionIndex) >= 0
|
||||||
|
? commentValue.indexOf(' ', selectedMentionIndex)
|
||||||
|
: commentValue.length;
|
||||||
|
const channelMention =
|
||||||
|
selectedMentionIndex >= 0 && selectionIndex <= mentionLengthIndex
|
||||||
|
? commentValue.substring(selectedMentionIndex, mentionLengthIndex)
|
||||||
|
: '';
|
||||||
|
|
||||||
const claimId = claim && claim.claim_id;
|
const claimId = claim && claim.claim_id;
|
||||||
const signingChannel = (claim && claim.signing_channel) || claim;
|
const signingChannel = (claim && claim.signing_channel) || claim;
|
||||||
const channelUri = signingChannel && signingChannel.permanent_url;
|
const channelUri = signingChannel && signingChannel.permanent_url;
|
||||||
|
@ -159,16 +171,21 @@ export function CommentCreate(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSelectMention(mentionValue) {
|
function handleSelectMention(mentionValue) {
|
||||||
const newCommentValue = commentWords.slice(0, -1).join(' ');
|
let newMentionValue = mentionValue.replace('lbry://', '');
|
||||||
let newMentionValue = mentionValue;
|
if (newMentionValue.includes('#')) {
|
||||||
if (mentionValue.includes('#')) {
|
const fullId = newMentionValue.substring(newMentionValue.indexOf('#') + 1, newMentionValue.length);
|
||||||
newMentionValue = mentionValue
|
newMentionValue = newMentionValue
|
||||||
.substring(0, mentionValue.indexOf('#') + 3)
|
.substring(0, newMentionValue.indexOf('#') + (fullId.length > 2 ? 2 : newMentionValue.length))
|
||||||
.replace('lbry://', '')
|
|
||||||
.replace('#', ':');
|
.replace('#', ':');
|
||||||
}
|
}
|
||||||
|
|
||||||
setCommentValue(newCommentValue + (commentWords.length > 1 ? ' ' : '') + `${newMentionValue} `);
|
setCommentValue(
|
||||||
|
commentValue.substring(0, selectedMentionIndex) +
|
||||||
|
`${newMentionValue}` +
|
||||||
|
(commentValue.length > mentionLengthIndex + 1
|
||||||
|
? commentValue.substring(mentionLengthIndex, commentValue.length)
|
||||||
|
: ' ')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function altEnterListener(e: SyntheticKeyboardEvent<*>) {
|
function altEnterListener(e: SyntheticKeyboardEvent<*>) {
|
||||||
|
@ -399,11 +416,6 @@ export function CommentCreate(props: Props) {
|
||||||
}
|
}
|
||||||
}, [fetchComment, shouldFetchComment, parentId]);
|
}, [fetchComment, shouldFetchComment, parentId]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const isMentioning = lastCommentWord && lastCommentWord.indexOf('@') === 0;
|
|
||||||
setChannelMention(isMentioning ? lastCommentWord : '');
|
|
||||||
}, [lastCommentWord]);
|
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
// Render
|
// Render
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
@ -494,7 +506,7 @@ export function CommentCreate(props: Props) {
|
||||||
<ChannelMentionSuggestions
|
<ChannelMentionSuggestions
|
||||||
uri={uri}
|
uri={uri}
|
||||||
isLivestream={livestream}
|
isLivestream={livestream}
|
||||||
inputRef={formFieldRef && formFieldRef.current && formFieldRef.current.input}
|
inputRef={formFieldInputRef}
|
||||||
mentionTerm={channelMention}
|
mentionTerm={channelMention}
|
||||||
creatorUri={channelUri}
|
creatorUri={channelUri}
|
||||||
customSelectAction={handleSelectMention}
|
customSelectAction={handleSelectMention}
|
||||||
|
|
Loading…
Reference in a new issue