fix: emoji selection appends correctly to status input
When focus moves to the emoji picker the input loses focus, making selectionStart/selectionEnd unreliable. Replace the cursor-tracking insertion with a simple functional state updater that always appends the emoji to the end — reliable and appropriate for a short status field. Also removes the now-unused inputRef and useRef import. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,6 @@ import React, {
|
|||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import {
|
import {
|
||||||
@@ -350,7 +349,6 @@ function ProfileStatus() {
|
|||||||
const [statusMsg, setStatusMsg] = useState<string>(presence?.status ?? '');
|
const [statusMsg, setStatusMsg] = useState<string>(presence?.status ?? '');
|
||||||
const [clearAfter, setClearAfter] = useState('0');
|
const [clearAfter, setClearAfter] = useState('0');
|
||||||
const [emojiAnchor, setEmojiAnchor] = useState<RectCords>();
|
const [emojiAnchor, setEmojiAnchor] = useState<RectCords>();
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
|
||||||
|
|
||||||
// Initialise expiry from localStorage so timer survives page reload
|
// Initialise expiry from localStorage so timer survives page reload
|
||||||
const [expiryTs, setExpiryTs] = useState<number>(() => {
|
const [expiryTs, setExpiryTs] = useState<number>(() => {
|
||||||
@@ -393,25 +391,10 @@ function ProfileStatus() {
|
|||||||
);
|
);
|
||||||
const saving = saveState.status === AsyncStatus.Loading;
|
const saving = saveState.status === AsyncStatus.Loading;
|
||||||
|
|
||||||
const handleEmojiSelect = useCallback(
|
const handleEmojiSelect = useCallback((unicode: string) => {
|
||||||
(unicode: string) => {
|
|
||||||
const input = inputRef.current;
|
|
||||||
if (input) {
|
|
||||||
const start = input.selectionStart ?? statusMsg.length;
|
|
||||||
const end = input.selectionEnd ?? statusMsg.length;
|
|
||||||
const next = statusMsg.slice(0, start) + unicode + statusMsg.slice(end);
|
|
||||||
setStatusMsg(next);
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
input.focus();
|
|
||||||
input.setSelectionRange(start + unicode.length, start + unicode.length);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setStatusMsg((prev) => prev + unicode);
|
setStatusMsg((prev) => prev + unicode);
|
||||||
}
|
|
||||||
setEmojiAnchor(undefined);
|
setEmojiAnchor(undefined);
|
||||||
},
|
}, []);
|
||||||
[statusMsg],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleChange: ChangeEventHandler<HTMLInputElement> = (evt) => {
|
const handleChange: ChangeEventHandler<HTMLInputElement> = (evt) => {
|
||||||
setStatusMsg(evt.currentTarget.value);
|
setStatusMsg(evt.currentTarget.value);
|
||||||
@@ -460,7 +443,6 @@ function ProfileStatus() {
|
|||||||
<Box as="form" onSubmit={handleSubmit} gap="200" aria-disabled={saving}>
|
<Box as="form" onSubmit={handleSubmit} gap="200" aria-disabled={saving}>
|
||||||
<Box grow="Yes" direction="Column">
|
<Box grow="Yes" direction="Column">
|
||||||
<Input
|
<Input
|
||||||
ref={inputRef}
|
|
||||||
name="statusMsgInput"
|
name="statusMsgInput"
|
||||||
aria-label="Status message"
|
aria-label="Status message"
|
||||||
value={statusMsg}
|
value={statusMsg}
|
||||||
|
|||||||
Reference in New Issue
Block a user