diff --git a/package-lock.json b/package-lock.json index a360337..28309aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "classnames": "^2.3.1", "color-hash": "^2.0.1", "events": "^3.3.0", + "lodash-move": "^1.1.1", "matrix-js-sdk": "^12.0.1", "react": "^17.0.0", "react-dom": "^17.0.0", @@ -1099,6 +1100,19 @@ "verror": "1.10.0" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-move": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/lodash-move/-/lodash-move-1.1.1.tgz", + "integrity": "sha1-WfduDxrFfm2Gg/UxvsB8W26k40g=", + "dependencies": { + "lodash": "^4.6.1" + } + }, "node_modules/loglevel": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", @@ -2530,6 +2544,19 @@ "verror": "1.10.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash-move": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/lodash-move/-/lodash-move-1.1.1.tgz", + "integrity": "sha1-WfduDxrFfm2Gg/UxvsB8W26k40g=", + "requires": { + "lodash": "^4.6.1" + } + }, "loglevel": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", diff --git a/package.json b/package.json index 1dbbe13..923e308 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "classnames": "^2.3.1", "color-hash": "^2.0.1", "events": "^3.3.0", + "lodash-move": "^1.1.1", "matrix-js-sdk": "^12.0.1", "react": "^17.0.0", "react-dom": "^17.0.0", diff --git a/src/GridDemo.jsx b/src/GridDemo.jsx index ddf856e..380f270 100644 --- a/src/GridDemo.jsx +++ b/src/GridDemo.jsx @@ -1,8 +1,9 @@ import React, { useCallback, useEffect, useRef, useState } from "react"; import { useDrag } from "react-use-gesture"; -import { useSprings, animated, useSpring } from "@react-spring/web"; +import { useSprings, animated } from "@react-spring/web"; import styles from "./GridDemo.module.css"; import useMeasure from "react-use-measure"; +import moveArrItem from "lodash-move"; function isInside([x, y], targetTile) { const left = targetTile.x; @@ -128,7 +129,9 @@ export function GridDemo() { const stream = await navigator.mediaDevices.getUserMedia({ video: true }); setStream(stream); tileOrderRef.current.push(tileOrderRef.current.length); + setTileState(() => { + console.log("startWebcam"); const tiles = [{ stream, key: tileKey.current++, remove: false }]; const tilePositions = getTilePositions(tiles, gridBounds); return { tiles, tilePositions }; @@ -141,6 +144,7 @@ export function GridDemo() { tileOrderRef.current.push(tileOrderRef.current.length); setTileState(({ tiles }) => { + console.log("addTile"); const newTiles = [ ...tiles, { stream: newStream, key: tileKey.current++, remove: false }, @@ -193,10 +197,11 @@ export function GridDemo() { }, [gridBounds]); const animate = useCallback( - (order) => (index) => { - const tileIndex = order[index]; + (tileIndex) => { + const tileOrder = tileOrderRef.current; + const order = tileOrder.indexOf(tileIndex); const tile = tiles[tileIndex]; - const tilePosition = tilePositions[tileIndex]; + const tilePosition = tilePositions[order]; const draggingTile = draggingTileRef.current; const dragging = draggingTile && tile.key === draggingTile.key; const remove = tile.remove; @@ -205,8 +210,8 @@ export function GridDemo() { return { width: tilePosition.width, height: tilePosition.height, - x: tilePosition.x + draggingTile.x, - y: tilePosition.y + draggingTile.y, + x: draggingTile.offsetX + draggingTile.x, + y: draggingTile.offsetY + draggingTile.y, scale: 1.1, opacity: 1, zIndex: 1, @@ -237,47 +242,62 @@ export function GridDemo() { [tiles, tilePositions] ); - const [springs, api] = useSprings( - tiles.length, - animate(tileOrderRef.current), - [tilePositions, tiles] - ); + const [springs, api] = useSprings(tiles.length, animate, [ + tilePositions, + tiles, + ]); - const bind = useDrag(({ args: [index], active, xy, movement }) => { - let order = tileOrderRef.current; + const bind = useDrag(({ args: [key], active, xy, movement }) => { + const tileOrder = tileOrderRef.current; - const tileIndex = tileOrderRef.current[index]; - const tile = tiles[tileIndex]; + const dragTileIndex = tiles.findIndex((tile) => tile.key === key); + const dragTile = tiles[dragTileIndex]; + + const dragTileOrder = tileOrder.indexOf(dragTileIndex); const cursorPosition = [xy[0] - gridBounds.left, xy[1] - gridBounds.top]; - for (let i = 0; i < tileOrderRef.current.length; i++) { - if (i === index) { + for ( + let hoverTileIndex = 0; + hoverTileIndex < tiles.length; + hoverTileIndex++ + ) { + const hoverTile = tiles[hoverTileIndex]; + const hoverTileOrder = tileOrder.indexOf(hoverTileIndex); + const hoverTilePosition = tilePositions[hoverTileOrder]; + + if (hoverTile.key === key) { continue; } - const hoverTileIndex = tileOrderRef.current[i]; - const hoverTilePosition = tilePositions[hoverTileIndex]; - if (isInside(cursorPosition, hoverTilePosition)) { - // TODO: Figure out swapping - // order[i] = tileIndex; - // order[index] = i; + tileOrderRef.current = moveArrItem( + tileOrder, + dragTileOrder, + hoverTileOrder + ); break; } } if (active) { - draggingTileRef.current = { - key: tile.key, - x: movement[0], - y: movement[1], - }; + if (!draggingTileRef.current) { + const tilePosition = tilePositions[dragTileOrder]; + + draggingTileRef.current = { + key: dragTile.key, + offsetX: tilePosition.x, + offsetY: tilePosition.y, + }; + } + + draggingTileRef.current.x = movement[0]; + draggingTileRef.current.y = movement[1]; } else { draggingTileRef.current = null; } - api.start(animate(order)); + api.start(animate); }); return ( @@ -300,7 +320,7 @@ export function GridDemo() { return ( ); @@ -331,6 +352,7 @@ function ParticipantTile({ style, stream, remove, tileKey, ...rest }) { return ( +
{tileKey}
); diff --git a/src/GridDemo.module.css b/src/GridDemo.module.css index 7e71c6e..7dbf2e8 100644 --- a/src/GridDemo.module.css +++ b/src/GridDemo.module.css @@ -26,4 +26,12 @@ width: 100%; height: 100%; object-fit: cover; +} + +.participantName { + position: absolute; + bottom: 0; + right: 0; + background-color: rgba(0, 0, 0, 0.2); + padding: 8px 24px; } \ No newline at end of file