Double tap to toggle moved MediaControl
This commit is contained in:
parent
0d1024ff61
commit
d12d87a796
@ -1322,6 +1322,14 @@ const MediaControl: React.FC<MediaControlProps> = ({
|
||||
width?: number;
|
||||
height?: number;
|
||||
}>({ translate: [0, 0] });
|
||||
// Remember last released moveable position/size so we can restore to it
|
||||
const lastSavedRef = useRef<{
|
||||
translate: [number, number];
|
||||
width?: number;
|
||||
height?: number;
|
||||
} | null>(null);
|
||||
// Whether the target is currently snapped to the spacer (true) or in a free position (false)
|
||||
const [isAttached, setIsAttached] = useState<boolean>(true);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const targetRef = useRef<HTMLDivElement>(null);
|
||||
const spacerRef = useRef<HTMLDivElement>(null);
|
||||
@ -1341,6 +1349,40 @@ const MediaControl: React.FC<MediaControlProps> = ({
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Double-click toggles between spacer-attached and last saved free position
|
||||
const handleDoubleClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
// Ignore double-clicks on control buttons
|
||||
const targetEl = e.target as HTMLElement | null;
|
||||
if (targetEl && (targetEl.closest("button") || targetEl.closest(".MuiIconButton-root"))) return;
|
||||
|
||||
if (!targetRef.current || !spacerRef.current) return;
|
||||
|
||||
// If currently attached to spacer -> restore to last saved moveable position
|
||||
if (isAttached) {
|
||||
const last = lastSavedRef.current;
|
||||
if (last) {
|
||||
targetRef.current.style.transform = `translate(${last.translate[0]}px, ${last.translate[1]}px)`;
|
||||
if (typeof last.width === "number") targetRef.current.style.width = `${last.width}px`;
|
||||
if (typeof last.height === "number") targetRef.current.style.height = `${last.height}px`;
|
||||
setFrame(last);
|
||||
setIsAttached(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If not attached -> move back to spacer (origin)
|
||||
const spacerRect = spacerRef.current.getBoundingClientRect();
|
||||
targetRef.current.style.transform = "translate(0px, 0px)";
|
||||
targetRef.current.style.width = `${spacerRect.width}px`;
|
||||
targetRef.current.style.height = `${spacerRect.height}px`;
|
||||
setFrame({ translate: [0, 0], width: spacerRect.width, height: spacerRect.height });
|
||||
setIsAttached(true);
|
||||
},
|
||||
[isAttached]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(
|
||||
`media-agent - MediaControl mounted for peer ${peer?.peer_name}, local=${peer?.local}, hasSrcObject=${!!peer
|
||||
@ -1579,10 +1621,11 @@ const MediaControl: React.FC<MediaControlProps> = ({
|
||||
opacity: isDragging ? 1 : 0.3,
|
||||
transition: "opacity 0.2s",
|
||||
}}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
>
|
||||
{isDragging && (
|
||||
<div
|
||||
style={{
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
@ -1590,10 +1633,11 @@ const MediaControl: React.FC<MediaControlProps> = ({
|
||||
fontSize: "0.7em",
|
||||
color: "#888",
|
||||
pointerEvents: "none",
|
||||
userSelect: "none",
|
||||
}}
|
||||
>
|
||||
Drop here
|
||||
</div>
|
||||
</Box>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -1602,6 +1646,7 @@ const MediaControl: React.FC<MediaControlProps> = ({
|
||||
ref={targetRef}
|
||||
className={`MediaControl ${className}`}
|
||||
data-peer={peer.session_id}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "0px",
|
||||
@ -1651,6 +1696,7 @@ const MediaControl: React.FC<MediaControlProps> = ({
|
||||
srcObject={peer.attributes.srcObject}
|
||||
local={peer.local}
|
||||
muted={peer.local || muted}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
/>
|
||||
<WebRTCStatus isNegotiating={peer.isNegotiating || false} connectionState={peer.connectionState} />
|
||||
<WebRTCStatus isNegotiating={peer.isNegotiating || false} connectionState={peer.connectionState} />
|
||||
@ -1711,19 +1757,29 @@ const MediaControl: React.FC<MediaControlProps> = ({
|
||||
const shouldSnap = checkSnapBack(matrix.m41, matrix.m42);
|
||||
if (shouldSnap) {
|
||||
targetRef.current.style.transform = "translate(0px, 0px)";
|
||||
setFrame({ translate: [0, 0], width: frame.width, height: frame.height });
|
||||
// Snap back to spacer origin
|
||||
setFrame((prev) => ({ translate: [0, 0], width: prev.width, height: prev.height }));
|
||||
if (spacerRef.current) {
|
||||
const spacerRect = spacerRef.current.getBoundingClientRect();
|
||||
targetRef.current.style.width = `${spacerRect.width}px`;
|
||||
targetRef.current.style.height = `${spacerRect.height}px`;
|
||||
setFrame({ translate: [0, 0] });
|
||||
setFrame({ translate: [0, 0], width: spacerRect.width, height: spacerRect.height });
|
||||
}
|
||||
// Remember that we're attached to spacer
|
||||
setIsAttached(true);
|
||||
} else {
|
||||
setFrame({
|
||||
translate: [matrix.m41, matrix.m42],
|
||||
width: frame.width,
|
||||
height: frame.height,
|
||||
});
|
||||
// Save last free position
|
||||
lastSavedRef.current = {
|
||||
translate: [matrix.m41, matrix.m42],
|
||||
width: frame.width,
|
||||
height: frame.height,
|
||||
};
|
||||
setIsAttached(false);
|
||||
}
|
||||
} else {
|
||||
setFrame({ translate: [0, 0], width: frame.width, height: frame.height });
|
||||
@ -1748,6 +1804,26 @@ const MediaControl: React.FC<MediaControlProps> = ({
|
||||
}}
|
||||
onResizeEnd={() => {
|
||||
setIsDragging(false);
|
||||
// Save last size when user finishes resizing; preserve translate
|
||||
if (targetRef.current) {
|
||||
const computedStyle = getComputedStyle(targetRef.current);
|
||||
const transform = computedStyle.transform;
|
||||
let tx = 0,
|
||||
ty = 0;
|
||||
if (transform && transform !== "none") {
|
||||
const matrix = new DOMMatrix(transform);
|
||||
tx = matrix.m41;
|
||||
ty = matrix.m42;
|
||||
}
|
||||
lastSavedRef.current = {
|
||||
translate: [tx, ty],
|
||||
width: frame.width,
|
||||
height: frame.height,
|
||||
};
|
||||
// If we resized while attached to spacer, consider that we are free
|
||||
if (tx !== 0 || ty !== 0) setIsAttached(false);
|
||||
else setIsAttached(true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user