Add sub groups to group table
This commit is contained in:
parent
ab800150ec
commit
05968c1964
@ -5,7 +5,7 @@
|
||||
"dependencies": {
|
||||
"@babylonjs/core": "^4.2.0",
|
||||
"@babylonjs/loaders": "^4.2.0",
|
||||
"@dnd-kit/core": "^3.0.2",
|
||||
"@dnd-kit/core": "3.0.2",
|
||||
"@dnd-kit/sortable": "^3.0.1",
|
||||
"@mitchemmc/dexie-export-import": "^1.0.1",
|
||||
"@msgpack/msgpack": "^2.4.1",
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React from "react";
|
||||
import { Flex, Image as UIImage, IconButton, Box, Text, Badge } from "theme-ui";
|
||||
import { Flex, IconButton, Box, Text, Badge, Grid } from "theme-ui";
|
||||
|
||||
import EditTileIcon from "../icons/EditTileIcon";
|
||||
|
||||
function Tile({
|
||||
src,
|
||||
title,
|
||||
isSelected,
|
||||
onSelect,
|
||||
@ -13,6 +12,8 @@ function Tile({
|
||||
canEdit,
|
||||
badges,
|
||||
editTitle,
|
||||
columns,
|
||||
children,
|
||||
}) {
|
||||
return (
|
||||
<Flex
|
||||
@ -34,21 +35,21 @@ function Tile({
|
||||
onSelect();
|
||||
}}
|
||||
onDoubleClick={onDoubleClick}
|
||||
aria-label={title}
|
||||
>
|
||||
{src && (
|
||||
<UIImage
|
||||
<Grid
|
||||
columns={columns}
|
||||
sx={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "contain",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
gridGap: 0,
|
||||
}}
|
||||
src={src}
|
||||
alt={title}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</Grid>
|
||||
<Flex
|
||||
sx={{
|
||||
position: "absolute",
|
||||
@ -116,7 +117,6 @@ function Tile({
|
||||
}
|
||||
|
||||
Tile.defaultProps = {
|
||||
src: "",
|
||||
title: "",
|
||||
isSelected: false,
|
||||
onSelect: () => {},
|
||||
@ -126,6 +126,7 @@ Tile.defaultProps = {
|
||||
canEdit: false,
|
||||
badges: [],
|
||||
editTitle: "Edit",
|
||||
columns: "1fr",
|
||||
};
|
||||
|
||||
export default Tile;
|
||||
|
@ -1,16 +1,18 @@
|
||||
import React from "react";
|
||||
import { Image } from "theme-ui";
|
||||
|
||||
import Tile from "../Tile";
|
||||
|
||||
function DiceTile({ dice, isSelected, onDiceSelect, onDone }) {
|
||||
return (
|
||||
<Tile
|
||||
src={dice.preview}
|
||||
title={dice.name}
|
||||
isSelected={isSelected}
|
||||
onSelect={() => onDiceSelect(dice)}
|
||||
onDoubleClick={() => onDone(dice)}
|
||||
/>
|
||||
>
|
||||
<Image src={dice.preview}></Image>
|
||||
</Tile>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,8 @@ function SortableTiles({ groups, onGroupChange, renderTile, children }) {
|
||||
function handleDragEnd({ active, over }) {
|
||||
setDragId();
|
||||
if (active && over && active.id !== over.id) {
|
||||
const oldIndex = groups.indexOf(active.id);
|
||||
const newIndex = groups.indexOf(over.id);
|
||||
const oldIndex = groups.findIndex((group) => group.id === active.id);
|
||||
const newIndex = groups.findIndex((group) => group.id === over.id);
|
||||
onGroupChange(arrayMove(groups, oldIndex, newIndex));
|
||||
}
|
||||
}
|
||||
@ -53,7 +53,7 @@ function SortableTiles({ groups, onGroupChange, renderTile, children }) {
|
||||
<DragOverlay dropAnimation={null}>
|
||||
{dragId && (
|
||||
<animated.div style={dragBounce}>
|
||||
{renderTile(dragId)}
|
||||
{renderTile(groups.find((group) => group.id === dragId))}
|
||||
</animated.div>
|
||||
)}
|
||||
</DragOverlay>,
|
||||
|
@ -1,9 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
import Tile from "../Tile";
|
||||
|
||||
import { useDataURL } from "../../contexts/AssetsContext";
|
||||
import { mapSources as defaultMapSources } from "../../maps";
|
||||
import MapTileImage from "./MapTileImage";
|
||||
|
||||
function MapTile({
|
||||
map,
|
||||
@ -14,16 +12,8 @@ function MapTile({
|
||||
canEdit,
|
||||
badges,
|
||||
}) {
|
||||
const mapURL = useDataURL(
|
||||
map,
|
||||
defaultMapSources,
|
||||
undefined,
|
||||
map.type === "file"
|
||||
);
|
||||
|
||||
return (
|
||||
<Tile
|
||||
src={mapURL}
|
||||
title={map.name}
|
||||
isSelected={isSelected}
|
||||
onSelect={() => onMapSelect(map)}
|
||||
@ -32,7 +22,9 @@ function MapTile({
|
||||
canEdit={canEdit}
|
||||
badges={badges}
|
||||
editTitle="Edit Map"
|
||||
/>
|
||||
>
|
||||
<MapTileImage map={map} />
|
||||
</Tile>
|
||||
);
|
||||
}
|
||||
|
||||
|
33
src/components/map/MapTileGroup.js
Normal file
33
src/components/map/MapTileGroup.js
Normal file
@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
|
||||
import Tile from "../Tile";
|
||||
import MapTileImage from "./MapTileImage";
|
||||
|
||||
function MapTileGroup({
|
||||
group,
|
||||
maps,
|
||||
isSelected,
|
||||
onGroupSelect,
|
||||
onOpen,
|
||||
canOpen,
|
||||
}) {
|
||||
return (
|
||||
<Tile
|
||||
title={group.name}
|
||||
isSelected={isSelected}
|
||||
// onSelect={() => onGroupSelect(group)}
|
||||
// onDoubleClick={() => canOpen && onOpen()}
|
||||
columns="1fr 1fr"
|
||||
>
|
||||
{maps.slice(0, 4).map((map) => (
|
||||
<MapTileImage
|
||||
sx={{ padding: 1, borderRadius: "8px" }}
|
||||
map={map}
|
||||
key={map.id}
|
||||
/>
|
||||
))}
|
||||
</Tile>
|
||||
);
|
||||
}
|
||||
|
||||
export default MapTileGroup;
|
18
src/components/map/MapTileImage.js
Normal file
18
src/components/map/MapTileImage.js
Normal file
@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
import { Image } from "theme-ui";
|
||||
|
||||
import { useDataURL } from "../../contexts/AssetsContext";
|
||||
import { mapSources as defaultMapSources } from "../../maps";
|
||||
|
||||
function MapTileImage({ map, sx }) {
|
||||
const mapURL = useDataURL(
|
||||
map,
|
||||
defaultMapSources,
|
||||
undefined,
|
||||
map.type === "file"
|
||||
);
|
||||
|
||||
return <Image sx={sx} src={mapURL}></Image>;
|
||||
}
|
||||
|
||||
export default MapTileImage;
|
@ -6,6 +6,7 @@ import RemoveMapIcon from "../../icons/RemoveMapIcon";
|
||||
import ResetMapIcon from "../../icons/ResetMapIcon";
|
||||
|
||||
import MapTile from "./MapTile";
|
||||
import MapTileGroup from "./MapTileGroup";
|
||||
import Link from "../Link";
|
||||
import FilterBar from "../FilterBar";
|
||||
|
||||
@ -53,8 +54,9 @@ function MapTiles({
|
||||
(map) => map.type === "default"
|
||||
);
|
||||
|
||||
function mapToTile(mapId) {
|
||||
const map = maps.find((map) => map.id === mapId);
|
||||
function groupToMapTile(group) {
|
||||
if (group.type === "item") {
|
||||
const map = maps.find((map) => map.id === group.id);
|
||||
const isSelected = selectedMaps.includes(map);
|
||||
return (
|
||||
<MapTile
|
||||
@ -64,13 +66,23 @@ function MapTiles({
|
||||
onMapSelect={onMapSelect}
|
||||
onMapEdit={onMapEdit}
|
||||
onDone={onDone}
|
||||
size={layout.tileSize}
|
||||
canEdit={
|
||||
isSelected && selectMode === "single" && selectedMaps.length === 1
|
||||
}
|
||||
badges={[`${map.grid.size.x}x${map.grid.size.y}`]}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<MapTileGroup
|
||||
key={group.id}
|
||||
group={group}
|
||||
maps={group.items.map((item) =>
|
||||
maps.find((map) => map.id === item.id)
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const multipleSelected = selectedMaps.length > 1;
|
||||
@ -79,7 +91,7 @@ function MapTiles({
|
||||
<SortableTiles
|
||||
groups={groups}
|
||||
onGroupChange={onMapsGroup}
|
||||
renderTile={mapToTile}
|
||||
renderTile={groupToMapTile}
|
||||
>
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<FilterBar
|
||||
@ -110,9 +122,9 @@ function MapTiles({
|
||||
columns={layout.gridTemplate}
|
||||
onClick={() => onMapSelect()}
|
||||
>
|
||||
{groups.map((mapId) => (
|
||||
<Sortable id={mapId} key={mapId}>
|
||||
{mapToTile(mapId)}
|
||||
{groups.map((group) => (
|
||||
<Sortable id={group.id} key={group.id}>
|
||||
{groupToMapTile(group)}
|
||||
</Sortable>
|
||||
))}
|
||||
</Grid>
|
||||
|
@ -29,6 +29,7 @@ function TokenBar({ onMapTokenStateCreate }) {
|
||||
function handleDragEnd({ active }) {
|
||||
setDragId(null);
|
||||
const token = tokensById[active.id];
|
||||
console.log("Drag", active);
|
||||
if (token) {
|
||||
// TODO: Get drag position
|
||||
const tokenState = createTokenState(token, { x: 0, y: 0 }, userId);
|
||||
@ -36,8 +37,9 @@ function TokenBar({ onMapTokenStateCreate }) {
|
||||
}
|
||||
}
|
||||
const tokens = tokenGroups
|
||||
.map((tokenId) => tokensById[tokenId])
|
||||
.filter((token) => !token.hideInSidebar)
|
||||
.map((group) => tokensById[group.id])
|
||||
// TODO: Add group support
|
||||
.filter((token) => token && !token.hideInSidebar)
|
||||
.map((token) => (
|
||||
<Draggable id={token.id} key={token.id}>
|
||||
<ListToken token={token} />
|
||||
|
@ -1,10 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
import Tile from "../Tile";
|
||||
|
||||
import { useDataURL } from "../../contexts/AssetsContext";
|
||||
|
||||
import { tokenSources as defaultTokenSources } from "../../tokens";
|
||||
import TokenTileImage from "./TokenTileImage";
|
||||
|
||||
function TokenTile({
|
||||
token,
|
||||
@ -14,16 +11,8 @@ function TokenTile({
|
||||
canEdit,
|
||||
badges,
|
||||
}) {
|
||||
const tokenURL = useDataURL(
|
||||
token,
|
||||
defaultTokenSources,
|
||||
undefined,
|
||||
token.type === "file"
|
||||
);
|
||||
|
||||
return (
|
||||
<Tile
|
||||
src={tokenURL}
|
||||
title={token.name}
|
||||
isSelected={isSelected}
|
||||
onSelect={() => onTokenSelect(token)}
|
||||
@ -31,7 +20,9 @@ function TokenTile({
|
||||
canEdit={canEdit}
|
||||
badges={badges}
|
||||
editTitle="Edit Token"
|
||||
/>
|
||||
>
|
||||
<TokenTileImage token={token} />
|
||||
</Tile>
|
||||
);
|
||||
}
|
||||
|
||||
|
33
src/components/token/TokenTileGroup.js
Normal file
33
src/components/token/TokenTileGroup.js
Normal file
@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
|
||||
import Tile from "../Tile";
|
||||
import TokenTileImage from "./TokenTileImage";
|
||||
|
||||
function TokenTileGroup({
|
||||
group,
|
||||
tokens,
|
||||
isSelected,
|
||||
onGroupSelect,
|
||||
onOpen,
|
||||
canOpen,
|
||||
}) {
|
||||
return (
|
||||
<Tile
|
||||
title={group.name}
|
||||
isSelected={isSelected}
|
||||
// onSelect={() => onGroupSelect(group)}
|
||||
// onDoubleClick={() => canOpen && onOpen()}
|
||||
columns="1fr 1fr"
|
||||
>
|
||||
{tokens.slice(0, 4).map((token) => (
|
||||
<TokenTileImage
|
||||
sx={{ padding: 1, borderRadius: "8px" }}
|
||||
token={token}
|
||||
key={token.id}
|
||||
/>
|
||||
))}
|
||||
</Tile>
|
||||
);
|
||||
}
|
||||
|
||||
export default TokenTileGroup;
|
19
src/components/token/TokenTileImage.js
Normal file
19
src/components/token/TokenTileImage.js
Normal file
@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import { Image } from "theme-ui";
|
||||
|
||||
import { useDataURL } from "../../contexts/AssetsContext";
|
||||
|
||||
import { tokenSources as defaultTokenSources } from "../../tokens";
|
||||
|
||||
function TokenTileImage({ token, sx }) {
|
||||
const tokenURL = useDataURL(
|
||||
token,
|
||||
defaultTokenSources,
|
||||
undefined,
|
||||
token.type === "file"
|
||||
);
|
||||
|
||||
return <Image sx={sx} src={tokenURL}></Image>;
|
||||
}
|
||||
|
||||
export default TokenTileImage;
|
@ -7,6 +7,7 @@ import TokenHideIcon from "../../icons/TokenHideIcon";
|
||||
import TokenShowIcon from "../../icons/TokenShowIcon";
|
||||
|
||||
import TokenTile from "./TokenTile";
|
||||
import TokenTileGroup from "./TokenTileGroup";
|
||||
import Link from "../Link";
|
||||
import FilterBar from "../FilterBar";
|
||||
|
||||
@ -40,8 +41,9 @@ function TokenTiles({
|
||||
);
|
||||
let allTokensVisible = selectedTokens.every((token) => !token.hideInSidebar);
|
||||
|
||||
function tokenToTile(tokenId) {
|
||||
const token = tokens.find((token) => token.id === tokenId);
|
||||
function groupToTokenTile(group) {
|
||||
if (group.type === "item") {
|
||||
const token = tokens.find((token) => token.id === group.id);
|
||||
const isSelected = selectedTokens.includes(token);
|
||||
return (
|
||||
<TokenTile
|
||||
@ -59,6 +61,17 @@ function TokenTiles({
|
||||
badges={[`${token.defaultSize}x`]}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<TokenTileGroup
|
||||
key={group.id}
|
||||
group={group}
|
||||
tokens={group.items.map((item) =>
|
||||
tokens.find((token) => token.id === item.id)
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const multipleSelected = selectedTokens.length > 1;
|
||||
@ -82,7 +95,7 @@ function TokenTiles({
|
||||
<SortableTiles
|
||||
groups={groups}
|
||||
onGroupChange={onTokensGroup}
|
||||
renderTile={tokenToTile}
|
||||
renderTile={groupToTokenTile}
|
||||
>
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<FilterBar
|
||||
@ -112,9 +125,9 @@ function TokenTiles({
|
||||
columns={layout.gridTemplate}
|
||||
onClick={() => onTokenSelect()}
|
||||
>
|
||||
{groups.map((tokenId) => (
|
||||
<Sortable id={tokenId} key={tokenId}>
|
||||
{tokenToTile(tokenId)}
|
||||
{groups.map((group) => (
|
||||
<Sortable id={group.id} key={group.id}>
|
||||
{groupToTokenTile(group)}
|
||||
</Sortable>
|
||||
))}
|
||||
</Grid>
|
||||
|
@ -47,7 +47,7 @@ export function MapDataProvider({ children }) {
|
||||
const storedStates = await database.table("states").toArray();
|
||||
setMapStates(storedStates);
|
||||
const group = await database.table("groups").get("maps");
|
||||
const storedGroups = group.data;
|
||||
const storedGroups = group.items;
|
||||
setMapGroups(storedGroups);
|
||||
setMapsLoading(false);
|
||||
}
|
||||
@ -82,9 +82,9 @@ export function MapDataProvider({ children }) {
|
||||
await database.table("maps").add(map);
|
||||
await database.table("states").add(state);
|
||||
const group = await database.table("groups").get("maps");
|
||||
await database
|
||||
.table("groups")
|
||||
.update("maps", { data: [map.id, ...group.data] });
|
||||
await database.table("groups").update("maps", {
|
||||
items: [{ id: map.id, type: "item" }, ...group.items],
|
||||
});
|
||||
},
|
||||
[database]
|
||||
);
|
||||
@ -146,7 +146,7 @@ export function MapDataProvider({ children }) {
|
||||
async (groups) => {
|
||||
// Update group state immediately to avoid animation delay
|
||||
setMapGroups(groups);
|
||||
await database.table("groups").update("maps", { data: groups });
|
||||
await database.table("groups").update("maps", { items: groups });
|
||||
},
|
||||
[database]
|
||||
);
|
||||
@ -207,7 +207,7 @@ export function MapDataProvider({ children }) {
|
||||
}
|
||||
if (change.table === "groups") {
|
||||
if (change.type === 2 && change.key === "maps") {
|
||||
setMapGroups(change.obj.data);
|
||||
setMapGroups(change.obj.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ export function TokenDataProvider({ children }) {
|
||||
}
|
||||
setTokens(storedTokens);
|
||||
const group = await database.table("groups").get("tokens");
|
||||
const storedGroups = group.data;
|
||||
const storedGroups = group.items;
|
||||
setTokenGroups(storedGroups);
|
||||
setTokensLoading(false);
|
||||
}
|
||||
@ -54,9 +54,9 @@ export function TokenDataProvider({ children }) {
|
||||
async (token) => {
|
||||
await database.table("tokens").add(token);
|
||||
const group = await database.table("groups").get("tokens");
|
||||
await database
|
||||
.table("groups")
|
||||
.update("tokens", { data: [token.id, ...group.data] });
|
||||
await database.table("groups").update("tokens", {
|
||||
items: [{ id: token.id, type: "item" }, ...group.items],
|
||||
});
|
||||
},
|
||||
[database]
|
||||
);
|
||||
@ -99,7 +99,7 @@ export function TokenDataProvider({ children }) {
|
||||
async (groups) => {
|
||||
// Update group state immediately to avoid animation delay
|
||||
setTokenGroups(groups);
|
||||
await database.table("groups").update("tokens", { data: groups });
|
||||
await database.table("groups").update("tokens", { items: groups });
|
||||
},
|
||||
[database]
|
||||
);
|
||||
@ -139,7 +139,7 @@ export function TokenDataProvider({ children }) {
|
||||
}
|
||||
if (change.table === "groups") {
|
||||
if (change.type === 2 && change.key === "tokens") {
|
||||
setTokenGroups(change.obj.data);
|
||||
setTokenGroups(change.obj.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,11 @@ function populate(db) {
|
||||
const tokens = getDefaultTokens(userId);
|
||||
db.table("tokens").bulkAdd(tokens);
|
||||
db.table("groups").bulkAdd([
|
||||
{ id: "maps", data: maps.map((map) => map.id) },
|
||||
{ id: "tokens", data: tokens.map((token) => token.id) },
|
||||
{ id: "maps", items: maps.map((map) => ({ id: map.id, type: "item" })) },
|
||||
{
|
||||
id: "tokens",
|
||||
items: tokens.map((token) => ({ id: token.id, type: "item" })),
|
||||
},
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
@ -639,23 +639,59 @@ export const versions = {
|
||||
tx.table("tokens").bulkAdd(tokens);
|
||||
});
|
||||
},
|
||||
// v1.9.0 -
|
||||
// v1.9.0 - Add new group table
|
||||
33(v) {
|
||||
v.stores({ groups: "id" }).upgrade(async (tx) => {
|
||||
function groupItems(items) {
|
||||
let groups = [];
|
||||
let subGroups = {};
|
||||
for (let item of items) {
|
||||
if (!item.group) {
|
||||
groups.push({ id: item.id, type: "item" });
|
||||
} else if (item.group in subGroups) {
|
||||
subGroups[item.group].items.push({ id: item.id, type: "item" });
|
||||
} else {
|
||||
subGroups[item.group] = {
|
||||
id: uuid(),
|
||||
type: "group",
|
||||
name: item.group,
|
||||
items: [{ id: item.id, type: "item" }],
|
||||
};
|
||||
}
|
||||
}
|
||||
groups.push(...Object.values(subGroups));
|
||||
return groups;
|
||||
}
|
||||
|
||||
let maps = await Dexie.waitFor(tx.table("maps").toArray());
|
||||
maps = maps.sort((a, b) => b.created - a.created);
|
||||
const mapIds = maps.map((map) => map.id);
|
||||
tx.table("groups").add({ id: "maps", data: mapIds });
|
||||
const mapGroupItems = groupItems(maps);
|
||||
tx.table("groups").add({ id: "maps", items: mapGroupItems });
|
||||
|
||||
let tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
||||
tokens = tokens.sort((a, b) => b.created - a.created);
|
||||
const tokenIds = tokens.map((token) => token.id);
|
||||
tx.table("groups").add({ id: "tokens", data: tokenIds });
|
||||
const tokenGroupItems = groupItems(tokens);
|
||||
tx.table("groups").add({ id: "tokens", items: tokenGroupItems });
|
||||
});
|
||||
},
|
||||
// v1.9.0 - Remove map and token group in respective tables
|
||||
34(v) {
|
||||
v.stores({}).upgrade((tx) => {
|
||||
tx.table("maps")
|
||||
.toCollection()
|
||||
.modify((map) => {
|
||||
delete map.group;
|
||||
});
|
||||
tx.table("tokens")
|
||||
.toCollection()
|
||||
.modify((token) => {
|
||||
delete token.group;
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const latestVersion = 33;
|
||||
export const latestVersion = 34;
|
||||
|
||||
/**
|
||||
* Load versions onto a database up to a specific version number
|
||||
|
@ -1803,7 +1803,7 @@
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@dnd-kit/core@^3.0.0", "@dnd-kit/core@^3.0.2":
|
||||
"@dnd-kit/core@3.0.2", "@dnd-kit/core@^3.0.0":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-3.0.2.tgz#e46ae11ef667aa5c31fddab21cf36ffd80d3ce5b"
|
||||
integrity sha512-L+rGnDYBb4BfYKDylzIBeODRIlJ+YVvo2iL9pVXsh317Nq7c9irCvi3XK8JnWD5QBw/3WZ5FmbPmTE91EKwKeA==
|
||||
@ -11894,6 +11894,7 @@ simple-peer@feross/simple-peer#694/head:
|
||||
resolved "https://codeload.github.com/feross/simple-peer/tar.gz/0d08d07b83ff3b8c60401688d80642d24dfeffe2"
|
||||
dependencies:
|
||||
debug "^4.0.1"
|
||||
err-code "^2.0.3"
|
||||
get-browser-rtc "^1.0.0"
|
||||
queue-microtask "^1.1.0"
|
||||
randombytes "^2.0.3"
|
||||
|
Loading…
Reference in New Issue
Block a user