import clsx from "clsx"; import { useContext, useEffect, useRef, useState } from "react"; import ReactDOM from "react-dom"; import { useSelector } from "react-redux"; import { ConfigUtils, Constants, CampaignUtils, characterEnvSelectors, } from "@dndbeyond/character-rules-engine/es"; import { Platform } from "@dndbeyond/event-pipeline-lib/shared"; import D20 from "@dndbeyond/fontawesome-cache/svgs/light/dice-d20.svg"; import { GameLogContext } from "@dndbeyond/game-log-components"; import { getMessageBroker } from "@dndbeyond/message-broker-lib"; import { CustomDiceRoller, rollerImport, } from "@dndbeyond/pocket-dimension-dice/components/CustomDiceRoller"; import "@dndbeyond/pocket-dimension-dice/components/CustomDiceRoller/index.css"; import { Context as DiceWorkerContext } from "@dndbeyond/pocket-dimension-dice/context"; import { instrumentDiceClear } from "@dndbeyond/pocket-dimension-dice/helpers/bi/instrumentDiceClear"; import { instrumentDiceContainerClose } from "@dndbeyond/pocket-dimension-dice/helpers/bi/instrumentDiceContainerClose"; import { instrumentDiceContainerOpen } from "@dndbeyond/pocket-dimension-dice/helpers/bi/instrumentDiceContainerOpen"; import { instrumentDiceRoll } from "@dndbeyond/pocket-dimension-dice/helpers/bi/instrumentDiceRoll"; import { useDiceSets } from "@dndbeyond/pocket-dimension-dice/hooks/useDiceSets"; import { useUserDiceDataStore } from "@dndbeyond/pocket-dimension-dice/hooks/useUserDiceDataStore"; import { AnchoredPopover } from "@dndbeyond/ttui/components/AnchoredPopover"; import { Button } from "~/components/Button"; import { useAuth } from "~/contexts/Authentication"; import { useCharacterEngine } from "~/hooks/useCharacterEngine"; import { useDispatch } from "~/hooks/useDispatch"; import { appEnvSelectors } from "../../selectors"; import styles from "./DiceContainer.module.css"; const location = "characterSheet"; export default function DiceContainer({ canShow = true, isVttView = false }) { const { nodeEnv, env } = useContext(DiceWorkerContext); const dispatch = useDispatch(); const diceEnabled = useSelector(appEnvSelectors.getDiceEnabled); const diceFeatureConfiguration = useSelector( appEnvSelectors.getDiceFeatureConfiguration ); const { campaign, characterName } = useCharacterEngine(); const user = useAuth(); const [{ entityId }] = useContext(GameLogContext); const canvasContainer = useRef(null); const [isCustomDiceRollerOpen, setIsCustomDiceRollerOpen] = useState(false); const diceSets = useDiceSets(nodeEnv, env); const setId = useUserDiceDataStore( (state) => state.getUserDiceData(Number(user?.id))?.setId ); const dmId = campaign ? String(CampaignUtils.getDmUserId(campaign)) : undefined; const isSheet = useSelector(characterEnvSelectors.getContext) === Constants.AppContextTypeEnum.SHEET; useEffect(() => { getMessageBroker().then((mb) => { if (mb && user?.id) { if (campaign) { mb.gameId = CampaignUtils.getId(campaign).toString(); } else { mb.gameId = undefined; } mb.userId = user.id; } ConfigUtils.configureRulesEngine({ messageBroker: mb }); }); }, [ campaign, diceFeatureConfiguration.apiEndpoint, diceFeatureConfiguration.assetBaseLocation, diceFeatureConfiguration.enabled, diceFeatureConfiguration.trackingId, dispatch, isSheet, user?.id, ]); if (isVttView) return null; return ReactDOM.createPortal(
{canShow && diceEnabled && ( { setIsCustomDiceRollerOpen(!isCustomDiceRollerOpen); // isCustomDiceRollerOpen is the previous state here if (isCustomDiceRollerOpen) { instrumentDiceContainerClose( user, Platform.Web, location, campaign?.id, undefined, env ); } else { instrumentDiceContainerOpen( user, Platform.Web, location, campaign?.id, undefined, env ); } }} themed onMouseEnter={rollerImport} > } floatingArrow floatingArrowClassName={styles.floatingArrow} > {diceSets && ( setIsCustomDiceRollerOpen(false)} onClose={() => setIsCustomDiceRollerOpen(false)} diceSets={diceSets} gameId={campaign?.id} visible={isCustomDiceRollerOpen} setId={setId} entityType="character" entityId={entityId} name={characterName ?? undefined} rollInstrumentationCallback={(eventPayload) => instrumentDiceRoll( user, eventPayload, Platform.Web, location, campaign?.id, undefined, env ) } clearDiceCallback={() => instrumentDiceClear( user, Platform.Web, location, campaign?.id, undefined, env ) } dmId={dmId} /> )} )} {/* We want this one so it is sticking around, also this is where the canvas goes when we append */} {/* */}
, document.body ); }