Finished grid demo
This commit is contained in:
		
					parent
					
						
							
								e68c9bee4a
							
						
					
				
			
			
				commit
				
					
						f303cb345f
					
				
			
		
					 4 changed files with 88 additions and 30 deletions
				
			
		
							
								
								
									
										27
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										27
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -11,6 +11,7 @@
 | 
				
			||||||
        "classnames": "^2.3.1",
 | 
					        "classnames": "^2.3.1",
 | 
				
			||||||
        "color-hash": "^2.0.1",
 | 
					        "color-hash": "^2.0.1",
 | 
				
			||||||
        "events": "^3.3.0",
 | 
					        "events": "^3.3.0",
 | 
				
			||||||
 | 
					        "lodash-move": "^1.1.1",
 | 
				
			||||||
        "matrix-js-sdk": "^12.0.1",
 | 
					        "matrix-js-sdk": "^12.0.1",
 | 
				
			||||||
        "react": "^17.0.0",
 | 
					        "react": "^17.0.0",
 | 
				
			||||||
        "react-dom": "^17.0.0",
 | 
					        "react-dom": "^17.0.0",
 | 
				
			||||||
| 
						 | 
					@ -1099,6 +1100,19 @@
 | 
				
			||||||
        "verror": "1.10.0"
 | 
					        "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": {
 | 
					    "node_modules/loglevel": {
 | 
				
			||||||
      "version": "1.7.1",
 | 
					      "version": "1.7.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
 | 
				
			||||||
| 
						 | 
					@ -2530,6 +2544,19 @@
 | 
				
			||||||
        "verror": "1.10.0"
 | 
					        "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": {
 | 
					    "loglevel": {
 | 
				
			||||||
      "version": "1.7.1",
 | 
					      "version": "1.7.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@
 | 
				
			||||||
    "classnames": "^2.3.1",
 | 
					    "classnames": "^2.3.1",
 | 
				
			||||||
    "color-hash": "^2.0.1",
 | 
					    "color-hash": "^2.0.1",
 | 
				
			||||||
    "events": "^3.3.0",
 | 
					    "events": "^3.3.0",
 | 
				
			||||||
 | 
					    "lodash-move": "^1.1.1",
 | 
				
			||||||
    "matrix-js-sdk": "^12.0.1",
 | 
					    "matrix-js-sdk": "^12.0.1",
 | 
				
			||||||
    "react": "^17.0.0",
 | 
					    "react": "^17.0.0",
 | 
				
			||||||
    "react-dom": "^17.0.0",
 | 
					    "react-dom": "^17.0.0",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,9 @@
 | 
				
			||||||
import React, { useCallback, useEffect, useRef, useState } from "react";
 | 
					import React, { useCallback, useEffect, useRef, useState } from "react";
 | 
				
			||||||
import { useDrag } from "react-use-gesture";
 | 
					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 styles from "./GridDemo.module.css";
 | 
				
			||||||
import useMeasure from "react-use-measure";
 | 
					import useMeasure from "react-use-measure";
 | 
				
			||||||
 | 
					import moveArrItem from "lodash-move";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function isInside([x, y], targetTile) {
 | 
					function isInside([x, y], targetTile) {
 | 
				
			||||||
  const left = targetTile.x;
 | 
					  const left = targetTile.x;
 | 
				
			||||||
| 
						 | 
					@ -128,7 +129,9 @@ export function GridDemo() {
 | 
				
			||||||
    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
 | 
					    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
 | 
				
			||||||
    setStream(stream);
 | 
					    setStream(stream);
 | 
				
			||||||
    tileOrderRef.current.push(tileOrderRef.current.length);
 | 
					    tileOrderRef.current.push(tileOrderRef.current.length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setTileState(() => {
 | 
					    setTileState(() => {
 | 
				
			||||||
 | 
					      console.log("startWebcam");
 | 
				
			||||||
      const tiles = [{ stream, key: tileKey.current++, remove: false }];
 | 
					      const tiles = [{ stream, key: tileKey.current++, remove: false }];
 | 
				
			||||||
      const tilePositions = getTilePositions(tiles, gridBounds);
 | 
					      const tilePositions = getTilePositions(tiles, gridBounds);
 | 
				
			||||||
      return { tiles, tilePositions };
 | 
					      return { tiles, tilePositions };
 | 
				
			||||||
| 
						 | 
					@ -141,6 +144,7 @@ export function GridDemo() {
 | 
				
			||||||
    tileOrderRef.current.push(tileOrderRef.current.length);
 | 
					    tileOrderRef.current.push(tileOrderRef.current.length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setTileState(({ tiles }) => {
 | 
					    setTileState(({ tiles }) => {
 | 
				
			||||||
 | 
					      console.log("addTile");
 | 
				
			||||||
      const newTiles = [
 | 
					      const newTiles = [
 | 
				
			||||||
        ...tiles,
 | 
					        ...tiles,
 | 
				
			||||||
        { stream: newStream, key: tileKey.current++, remove: false },
 | 
					        { stream: newStream, key: tileKey.current++, remove: false },
 | 
				
			||||||
| 
						 | 
					@ -193,10 +197,11 @@ export function GridDemo() {
 | 
				
			||||||
  }, [gridBounds]);
 | 
					  }, [gridBounds]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const animate = useCallback(
 | 
					  const animate = useCallback(
 | 
				
			||||||
    (order) => (index) => {
 | 
					    (tileIndex) => {
 | 
				
			||||||
      const tileIndex = order[index];
 | 
					      const tileOrder = tileOrderRef.current;
 | 
				
			||||||
 | 
					      const order = tileOrder.indexOf(tileIndex);
 | 
				
			||||||
      const tile = tiles[tileIndex];
 | 
					      const tile = tiles[tileIndex];
 | 
				
			||||||
      const tilePosition = tilePositions[tileIndex];
 | 
					      const tilePosition = tilePositions[order];
 | 
				
			||||||
      const draggingTile = draggingTileRef.current;
 | 
					      const draggingTile = draggingTileRef.current;
 | 
				
			||||||
      const dragging = draggingTile && tile.key === draggingTile.key;
 | 
					      const dragging = draggingTile && tile.key === draggingTile.key;
 | 
				
			||||||
      const remove = tile.remove;
 | 
					      const remove = tile.remove;
 | 
				
			||||||
| 
						 | 
					@ -205,8 +210,8 @@ export function GridDemo() {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
          width: tilePosition.width,
 | 
					          width: tilePosition.width,
 | 
				
			||||||
          height: tilePosition.height,
 | 
					          height: tilePosition.height,
 | 
				
			||||||
          x: tilePosition.x + draggingTile.x,
 | 
					          x: draggingTile.offsetX + draggingTile.x,
 | 
				
			||||||
          y: tilePosition.y + draggingTile.y,
 | 
					          y: draggingTile.offsetY + draggingTile.y,
 | 
				
			||||||
          scale: 1.1,
 | 
					          scale: 1.1,
 | 
				
			||||||
          opacity: 1,
 | 
					          opacity: 1,
 | 
				
			||||||
          zIndex: 1,
 | 
					          zIndex: 1,
 | 
				
			||||||
| 
						 | 
					@ -237,47 +242,62 @@ export function GridDemo() {
 | 
				
			||||||
    [tiles, tilePositions]
 | 
					    [tiles, tilePositions]
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [springs, api] = useSprings(
 | 
					  const [springs, api] = useSprings(tiles.length, animate, [
 | 
				
			||||||
    tiles.length,
 | 
					    tilePositions,
 | 
				
			||||||
    animate(tileOrderRef.current),
 | 
					    tiles,
 | 
				
			||||||
    [tilePositions, tiles]
 | 
					  ]);
 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const bind = useDrag(({ args: [index], active, xy, movement }) => {
 | 
					  const bind = useDrag(({ args: [key], active, xy, movement }) => {
 | 
				
			||||||
    let order = tileOrderRef.current;
 | 
					    const tileOrder = tileOrderRef.current;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const tileIndex = tileOrderRef.current[index];
 | 
					    const dragTileIndex = tiles.findIndex((tile) => tile.key === key);
 | 
				
			||||||
    const tile = tiles[tileIndex];
 | 
					    const dragTile = tiles[dragTileIndex];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dragTileOrder = tileOrder.indexOf(dragTileIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const cursorPosition = [xy[0] - gridBounds.left, xy[1] - gridBounds.top];
 | 
					    const cursorPosition = [xy[0] - gridBounds.left, xy[1] - gridBounds.top];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (let i = 0; i < tileOrderRef.current.length; i++) {
 | 
					    for (
 | 
				
			||||||
      if (i === index) {
 | 
					      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;
 | 
					        continue;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const hoverTileIndex = tileOrderRef.current[i];
 | 
					 | 
				
			||||||
      const hoverTilePosition = tilePositions[hoverTileIndex];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (isInside(cursorPosition, hoverTilePosition)) {
 | 
					      if (isInside(cursorPosition, hoverTilePosition)) {
 | 
				
			||||||
        // TODO: Figure out swapping
 | 
					        tileOrderRef.current = moveArrItem(
 | 
				
			||||||
        // order[i] = tileIndex;
 | 
					          tileOrder,
 | 
				
			||||||
        // order[index] = i;
 | 
					          dragTileOrder,
 | 
				
			||||||
 | 
					          hoverTileOrder
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (active) {
 | 
					    if (active) {
 | 
				
			||||||
 | 
					      if (!draggingTileRef.current) {
 | 
				
			||||||
 | 
					        const tilePosition = tilePositions[dragTileOrder];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        draggingTileRef.current = {
 | 
					        draggingTileRef.current = {
 | 
				
			||||||
        key: tile.key,
 | 
					          key: dragTile.key,
 | 
				
			||||||
        x: movement[0],
 | 
					          offsetX: tilePosition.x,
 | 
				
			||||||
        y: movement[1],
 | 
					          offsetY: tilePosition.y,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      draggingTileRef.current.x = movement[0];
 | 
				
			||||||
 | 
					      draggingTileRef.current.y = movement[1];
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      draggingTileRef.current = null;
 | 
					      draggingTileRef.current = null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    api.start(animate(order));
 | 
					    api.start(animate);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
| 
						 | 
					@ -300,7 +320,7 @@ export function GridDemo() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          return (
 | 
					          return (
 | 
				
			||||||
            <ParticipantTile
 | 
					            <ParticipantTile
 | 
				
			||||||
              {...bind(i)}
 | 
					              {...bind(tile.key)}
 | 
				
			||||||
              key={tile.key}
 | 
					              key={tile.key}
 | 
				
			||||||
              style={{
 | 
					              style={{
 | 
				
			||||||
                boxShadow: shadow.to(
 | 
					                boxShadow: shadow.to(
 | 
				
			||||||
| 
						 | 
					@ -308,6 +328,7 @@ export function GridDemo() {
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                ...style,
 | 
					                ...style,
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
 | 
					              tileKey={tile.key}
 | 
				
			||||||
              {...tile}
 | 
					              {...tile}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
| 
						 | 
					@ -331,6 +352,7 @@ function ParticipantTile({ style, stream, remove, tileKey, ...rest }) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <animated.div className={styles.participantTile} style={style} {...rest}>
 | 
					    <animated.div className={styles.participantTile} style={style} {...rest}>
 | 
				
			||||||
 | 
					      <div className={styles.participantName}>{tileKey}</div>
 | 
				
			||||||
      <video ref={videoRef} playsInline />
 | 
					      <video ref={videoRef} playsInline />
 | 
				
			||||||
    </animated.div>
 | 
					    </animated.div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,3 +27,11 @@
 | 
				
			||||||
  height: 100%;
 | 
					  height: 100%;
 | 
				
			||||||
  object-fit: cover;
 | 
					  object-fit: cover;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.participantName {
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  bottom: 0;
 | 
				
			||||||
 | 
					  right: 0;
 | 
				
			||||||
 | 
					  background-color: rgba(0, 0, 0, 0.2);
 | 
				
			||||||
 | 
					  padding: 8px 24px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue