v.0.3.6 message input box update
This commit is contained in:
@@ -12,20 +12,6 @@ function isEmojiOnly(str) {
|
||||
return emojiRegex.test(str.trim());
|
||||
}
|
||||
|
||||
|
||||
// Convert raw mention syntax to display HTML for the input mirror overlay
|
||||
function renderInputDisplay(raw) {
|
||||
// Escape HTML special chars first
|
||||
const escaped = raw
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
// Replace @[name](id) with bold @name span
|
||||
return escaped.replace(/@\[([^\]]+)\]\(\d+\)/g,
|
||||
(_, name) => `<strong class="mention-chip">@${name}</strong>`
|
||||
);
|
||||
}
|
||||
|
||||
export default function MessageInput({ group, replyTo, onCancelReply, onSend, onTyping }) {
|
||||
const [text, setText] = useState('');
|
||||
const [imageFile, setImageFile] = useState(null);
|
||||
@@ -39,7 +25,6 @@ export default function MessageInput({ group, replyTo, onCancelReply, onSend, on
|
||||
const [showAttachMenu, setShowAttachMenu] = useState(false);
|
||||
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
|
||||
const inputRef = useRef(null);
|
||||
const mirrorRef = useRef(null);
|
||||
const typingTimer = useRef(null);
|
||||
const wasTyping = useRef(false);
|
||||
const mentionStart = useRef(-1);
|
||||
@@ -109,10 +94,8 @@ export default function MessageInput({ group, replyTo, onCancelReply, onSend, on
|
||||
el.style.height = 'auto';
|
||||
const lineHeight = parseFloat(getComputedStyle(el).lineHeight);
|
||||
const maxHeight = lineHeight * 5 + 20;
|
||||
const newH = Math.min(el.scrollHeight, maxHeight) + 'px';
|
||||
el.style.height = newH;
|
||||
el.style.height = Math.min(el.scrollHeight, maxHeight) + 'px';
|
||||
el.style.overflowY = el.scrollHeight > maxHeight ? 'auto' : 'hidden';
|
||||
if (mirrorRef.current) mirrorRef.current.style.height = newH;
|
||||
|
||||
const cur = e.target.selectionStart;
|
||||
const lastAt = val.lastIndexOf('@', cur - 1);
|
||||
@@ -142,8 +125,8 @@ export default function MessageInput({ group, replyTo, onCancelReply, onSend, on
|
||||
const insertMention = (user) => {
|
||||
const before = text.slice(0, mentionStart.current);
|
||||
const after = text.slice(inputRef.current.selectionStart);
|
||||
const mention = `@[${user.display_name || user.name}](${user.id}) `;
|
||||
setText(before + mention + after);
|
||||
const name = user.display_name || user.name;
|
||||
setText(before + `@[${name}] ` + after);
|
||||
setShowMention(false);
|
||||
setMentionResults([]);
|
||||
inputRef.current.focus();
|
||||
@@ -177,10 +160,8 @@ export default function MessageInput({ group, replyTo, onCancelReply, onSend, on
|
||||
if (inputRef.current) {
|
||||
inputRef.current.style.height = 'auto';
|
||||
inputRef.current.style.overflowY = 'hidden';
|
||||
if (mirrorRef.current) mirrorRef.current.style.height = 'auto';
|
||||
}
|
||||
|
||||
// Tag emoji-only messages so they can be rendered large
|
||||
const emojiOnly = !!trimmed && isEmojiOnly(trimmed);
|
||||
await onSend({ content: trimmed || null, imageFile, linkPreview: lp, emojiOnly });
|
||||
};
|
||||
@@ -352,17 +333,10 @@ export default function MessageInput({ group, replyTo, onCancelReply, onSend, on
|
||||
)}
|
||||
|
||||
<div className="input-wrap">
|
||||
{/* Mirror overlay renders formatted mention text over the transparent textarea */}
|
||||
<div
|
||||
ref={mirrorRef}
|
||||
className="msg-input msg-input-mirror"
|
||||
aria-hidden="true"
|
||||
dangerouslySetInnerHTML={{ __html: renderInputDisplay(text) || '' }}
|
||||
/>
|
||||
<textarea
|
||||
ref={inputRef}
|
||||
className="msg-input msg-input-raw"
|
||||
placeholder={!text ? `Message ${group?.name || ''}...` : ''}
|
||||
className="msg-input"
|
||||
placeholder={`Message ${group?.name || ''}...`}
|
||||
value={text}
|
||||
onChange={handleChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
|
||||
Reference in New Issue
Block a user