Add edit handling too (not perfect, but useful later)

This commit is contained in:
Gigiaj 2025-06-15 23:05:06 -05:00
parent c8f490adfb
commit e820543951

View file

@ -2,6 +2,7 @@ import React from 'react';
import { useSpring, animated } from '@react-spring/web'; import { useSpring, animated } from '@react-spring/web';
import { useDrag } from 'react-use-gesture'; import { useDrag } from 'react-use-gesture';
import { Icon, Icons } from 'folds'; import { Icon, Icons } from 'folds';
import { MatrixClient, MatrixEvent } from 'matrix-js-sdk';
const DraggableMessageStyles = { const DraggableMessageStyles = {
container: { container: {
@ -9,7 +10,7 @@ const DraggableMessageStyles = {
overflow: 'hidden', overflow: 'hidden',
width: '100%', width: '100%',
}, },
replyIconContainer: { iconContainer: {
position: 'absolute', position: 'absolute',
top: 0, top: 0,
bottom: 0, bottom: 0,
@ -17,7 +18,7 @@ const DraggableMessageStyles = {
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
width: '80px', width: '150px',
}, },
messageContent: { messageContent: {
position: 'relative', position: 'relative',
@ -25,46 +26,76 @@ const DraggableMessageStyles = {
backgroundColor: 'var(--folds-color-Background-Main)', backgroundColor: 'var(--folds-color-Background-Main)',
width: '100%', width: '100%',
}, },
icon: {
position: 'absolute',
},
}; };
export function DraggableMessage({ children, onReply }) { export function DraggableMessage({
children,
onReply,
onEdit,
event,
mx,
}: {
children: React.ReactNode;
onReply: () => void;
onEdit: () => void;
event: MatrixEvent;
mx: MatrixClient;
}) {
const canEdit = mx.getUserId() === event.getSender();
const REPLY_THRESHOLD = 80; const REPLY_THRESHOLD = 80;
const EDIT_THRESHOLD = canEdit ? 250 : Infinity;
const [{ x, iconScale }, api] = useSpring(() => ({ const [{ x, replyOpacity, editOpacity, iconScale }, api] = useSpring(() => ({
x: 0, x: 0,
replyOpacity: 0,
editOpacity: 0,
iconScale: 0.5, iconScale: 0.5,
config: { tension: 250, friction: 25 }, config: { tension: 250, friction: 25 },
})); }));
const bind = useDrag( const bind = useDrag(
({ down, movement: [mx], direction: [xDir], vxvy: [vx], cancel }) => { ({ down, movement: [x], vxvy: [vx] }) => {
if (!down && Math.abs(xDir) < 0.7) {
cancel();
}
const xTarget = down ? Math.min(0, mx) : 0;
let scaleTarget = down
? 0.5 + Math.min(Math.abs(mx), REPLY_THRESHOLD) / (REPLY_THRESHOLD * 2)
: 0.5;
if (mx < -REPLY_THRESHOLD) {
onReply();
}
/*
if (!down) { if (!down) {
if (mx < -REPLY_THRESHOLD && vx < -0.5) { const finalDistance = Math.abs(x);
if (finalDistance > EDIT_THRESHOLD) {
onEdit();
} else if (finalDistance > REPLY_THRESHOLD) {
onReply(); onReply();
} }
} else {
if (mx < -REPLY_THRESHOLD) {
scaleTarget = 1;
}
} }
*/
const xTarget = down ? Math.min(0, x) : 0;
const distance = Math.abs(xTarget);
let newReplyOpacity = 0;
let newEditOpacity = 0;
let newScale = 1.0;
if (canEdit && distance > REPLY_THRESHOLD) {
newReplyOpacity = 0;
newEditOpacity = 1;
if (down && distance > EDIT_THRESHOLD) {
newScale = 1.1;
}
} else {
newReplyOpacity = 1;
newEditOpacity = 0;
newScale = 0.5 + (distance / REPLY_THRESHOLD) * 0.5;
}
if (distance < 5) {
newReplyOpacity = 0;
}
api.start({ api.start({
x: xTarget, x: xTarget,
iconScale: scaleTarget, replyOpacity: newReplyOpacity,
editOpacity: newEditOpacity,
iconScale: newScale,
}); });
}, },
{ {
@ -76,23 +107,29 @@ export function DraggableMessage({ children, onReply }) {
return ( return (
<div style={DraggableMessageStyles.container}> <div style={DraggableMessageStyles.container}>
<animated.div <div style={DraggableMessageStyles.iconContainer}>
style={{ <animated.div
...DraggableMessageStyles.replyIconContainer, style={{
transform: iconScale.to((s) => `scale(${s})`), ...DraggableMessageStyles.icon,
opacity: iconScale.to((s) => (s - 0.5) * 2), opacity: replyOpacity,
}} transform: iconScale.to((s) => `scale(${s})`),
> }}
<Icon src={Icons.ReplyArrow} size="200" /> >
</animated.div> <Icon src={Icons.ReplyArrow} size="200" />
</animated.div>
<animated.div <animated.div
{...bind()} style={{
style={{ ...DraggableMessageStyles.icon,
...DraggableMessageStyles.messageContent, opacity: editOpacity,
x, transform: iconScale.to((s) => `scale(${s})`),
}} }}
> >
<Icon src={Icons.Pencil} size="200" />
</animated.div>
</div>
<animated.div {...bind()} style={{ ...DraggableMessageStyles.messageContent, x }}>
{children} {children}
</animated.div> </animated.div>
</div> </div>