v0.7.4 bug fixes

This commit is contained in:
2026-03-11 18:36:07 -04:00
parent 6ad9584ea9
commit 8202c838f5
11 changed files with 132 additions and 71 deletions

View File

@@ -62,6 +62,60 @@ export default function Message({ message: msg, prevMessage, currentUser, onRepl
msg.group_owner_id === currentUser.id
);
// Close emoji picker when clicking outside
useEffect(() => {
if (!showEmojiPicker) return;
const handler = (e) => {
if (pickerRef.current && !pickerRef.current.contains(e.target)) {
setShowEmojiPicker(false);
}
};
document.addEventListener('mousedown', handler);
return () => document.removeEventListener('mousedown', handler);
}, [showEmojiPicker]);
// Close options menu on outside click
useEffect(() => {
if (!showOptionsMenu) return;
const close = (e) => {
if (optionsMenuRef.current && !optionsMenuRef.current.contains(e.target)) {
setShowOptionsMenu(false);
}
};
document.addEventListener('mousedown', close);
document.addEventListener('touchstart', close);
return () => {
document.removeEventListener('mousedown', close);
document.removeEventListener('touchstart', close);
};
}, [showOptionsMenu]);
const handleReact = (emoji) => {
onReact(msg.id, emoji);
setShowEmojiPicker(false);
};
const handleCopy = () => {
if (!msg.content) return;
navigator.clipboard.writeText(msg.content).catch(() => {});
};
const handleTogglePicker = () => {
if (!showEmojiPicker && wrapperRef.current) {
const rect = wrapperRef.current.getBoundingClientRect();
setPickerOpensDown(rect.top < 400);
}
setShowEmojiPicker(p => !p);
};
// Long press for mobile action menu
const handleTouchStart = () => {
longPressTimer.current = setTimeout(() => setShowOptionsMenu(true), 500);
};
const handleTouchEnd = () => {
if (longPressTimer.current) clearTimeout(longPressTimer.current);
};
// Deleted messages are filtered out by ChatWindow, but guard here too
if (isDeleted) return null;
@@ -85,61 +139,6 @@ export default function Message({ message: msg, prevMessage, currentUser, onRepl
if (r.user_id === currentUser.id) reactionMap[r.emoji].hasMe = true;
}
// Close emoji picker when clicking outside
useEffect(() => {
if (!showEmojiPicker) return;
const handler = (e) => {
if (pickerRef.current && !pickerRef.current.contains(e.target)) {
setShowEmojiPicker(false);
}
};
document.addEventListener('mousedown', handler);
return () => document.removeEventListener('mousedown', handler);
}, [showEmojiPicker]);
const handleReact = (emoji) => {
onReact(msg.id, emoji);
setShowEmojiPicker(false);
};
const handleCopy = () => {
if (!msg.content) return;
navigator.clipboard.writeText(msg.content).catch(() => {});
};
const handleTogglePicker = () => {
if (!showEmojiPicker && wrapperRef.current) {
// If the message is in the top 400px of viewport, open picker downward
const rect = wrapperRef.current.getBoundingClientRect();
setPickerOpensDown(rect.top < 400);
}
setShowEmojiPicker(p => !p);
};
// Long press for mobile action menu
const handleTouchStart = () => {
longPressTimer.current = setTimeout(() => setShowOptionsMenu(true), 500);
};
const handleTouchEnd = () => {
if (longPressTimer.current) clearTimeout(longPressTimer.current);
};
// Close options menu on outside click
useEffect(() => {
if (!showOptionsMenu) return;
const close = (e) => {
if (optionsMenuRef.current && !optionsMenuRef.current.contains(e.target)) {
setShowOptionsMenu(false);
}
};
document.addEventListener('mousedown', close);
document.addEventListener('touchstart', close);
return () => {
document.removeEventListener('mousedown', close);
document.removeEventListener('touchstart', close);
};
}, [showOptionsMenu]);
const msgUser = {
id: msg.user_id,
name: msg.user_name,