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",
 | 
			
		||||
        "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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
      if (!draggingTileRef.current) {
 | 
			
		||||
        const tilePosition = tilePositions[dragTileOrder];
 | 
			
		||||
 | 
			
		||||
        draggingTileRef.current = {
 | 
			
		||||
        key: tile.key,
 | 
			
		||||
        x: movement[0],
 | 
			
		||||
        y: movement[1],
 | 
			
		||||
          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 (
 | 
			
		||||
            <ParticipantTile
 | 
			
		||||
              {...bind(i)}
 | 
			
		||||
              {...bind(tile.key)}
 | 
			
		||||
              key={tile.key}
 | 
			
		||||
              style={{
 | 
			
		||||
                boxShadow: shadow.to(
 | 
			
		||||
| 
						 | 
				
			
			@ -308,6 +328,7 @@ export function GridDemo() {
 | 
			
		|||
                ),
 | 
			
		||||
                ...style,
 | 
			
		||||
              }}
 | 
			
		||||
              tileKey={tile.key}
 | 
			
		||||
              {...tile}
 | 
			
		||||
            />
 | 
			
		||||
          );
 | 
			
		||||
| 
						 | 
				
			
			@ -331,6 +352,7 @@ function ParticipantTile({ style, stream, remove, tileKey, ...rest }) {
 | 
			
		|||
 | 
			
		||||
  return (
 | 
			
		||||
    <animated.div className={styles.participantTile} style={style} {...rest}>
 | 
			
		||||
      <div className={styles.participantName}>{tileKey}</div>
 | 
			
		||||
      <video ref={videoRef} playsInline />
 | 
			
		||||
    </animated.div>
 | 
			
		||||
  );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,3 +27,11 @@
 | 
			
		|||
  height: 100%;
 | 
			
		||||
  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