New source found from dndbeyond.com
This commit is contained in:
@@ -1,158 +1,173 @@
|
||||
import { useContext, useEffect, useRef } from "react";
|
||||
import clsx from "clsx";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { DispatchProp, useDispatch, useSelector } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
import { TypeScriptUtils } from "@dndbeyond/character-components/es";
|
||||
import {
|
||||
ApiAdapterUtils,
|
||||
CharacterTheme,
|
||||
ConfigUtils,
|
||||
rulesEngineSelectors,
|
||||
Constants,
|
||||
ApiException,
|
||||
CampaignDataContract,
|
||||
CampaignUtils,
|
||||
characterEnvSelectors,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
import { Dice, DiceNotifier, IRollContext } from "@dndbeyond/dice";
|
||||
import { DiceToolbar } from "@dndbeyond/dice-components";
|
||||
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 { appEnvActions } from "../../actions/appEnv";
|
||||
import {
|
||||
appEnvSelectors,
|
||||
characterRollContextSelectors,
|
||||
} from "../../selectors";
|
||||
import {
|
||||
DiceFeatureConfigurationState,
|
||||
SharedAppState,
|
||||
} from "../../stores/typings";
|
||||
import { AppLoggerUtils } from "../../utils";
|
||||
import { appEnvSelectors } from "../../selectors";
|
||||
import styles from "./DiceContainer.module.css";
|
||||
|
||||
interface Props extends DispatchProp {
|
||||
campaign: CampaignDataContract | null;
|
||||
canShow: boolean;
|
||||
theme: CharacterTheme;
|
||||
diceEnabled: boolean;
|
||||
diceFeatureConfiguration: DiceFeatureConfigurationState;
|
||||
characterRollContext: IRollContext;
|
||||
}
|
||||
const location = "characterSheet";
|
||||
|
||||
// <canvas id="dice-rolling-canvas" className={'dice-rolling-panel__container'} />
|
||||
// this is the canvas element that we will use to draw the dice
|
||||
// TODO: this is a temporary solution, we need to find a better way to do this
|
||||
// waiting for adventure team to provide a better solution
|
||||
const canvasElement = document.createElement("canvas");
|
||||
canvasElement.id = "dice-rolling-canvas";
|
||||
canvasElement.classList.add("dice-rolling-panel__container");
|
||||
|
||||
export default function DiceContainer({ canShow = true }) {
|
||||
export default function DiceContainer({ canShow = true, isVttView = false }) {
|
||||
const { nodeEnv, env } = useContext(DiceWorkerContext);
|
||||
const dispatch = useDispatch();
|
||||
const theme = useSelector(rulesEngineSelectors.getCharacterTheme);
|
||||
const diceEnabled = useSelector(appEnvSelectors.getDiceEnabled);
|
||||
const diceFeatureConfiguration = useSelector(
|
||||
appEnvSelectors.getDiceFeatureConfiguration
|
||||
);
|
||||
const characterRollContext = useSelector(
|
||||
characterRollContextSelectors.getCharacterRollContext
|
||||
);
|
||||
const campaign = useSelector(rulesEngineSelectors.getCampaign);
|
||||
const userConfigApi = "/diceuserconfig/v1/get";
|
||||
const authUser = useAuth();
|
||||
let userId: string | null = null;
|
||||
if (authUser?.id) {
|
||||
userId = authUser.id;
|
||||
}
|
||||
const [{ messageTargetOptions, defaultMessageTargetOption }] =
|
||||
useContext(GameLogContext);
|
||||
const { campaign, characterName } = useCharacterEngine();
|
||||
const user = useAuth();
|
||||
const [{ entityId }] = useContext(GameLogContext);
|
||||
const canvasContainer = useRef<HTMLDivElement | null>(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(() => {
|
||||
if (!canvasContainer.current?.contains(canvasElement)) {
|
||||
canvasContainer.current?.appendChild(canvasElement);
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
getMessageBroker().then((mb) => {
|
||||
if (mb && campaign && userId) {
|
||||
mb.gameId = isSheet ? CampaignUtils.getId(campaign).toString() : "0";
|
||||
mb.userId = userId;
|
||||
if (mb && user?.id) {
|
||||
if (campaign) {
|
||||
mb.gameId = CampaignUtils.getId(campaign).toString();
|
||||
} else {
|
||||
mb.gameId = undefined;
|
||||
}
|
||||
|
||||
mb.userId = user.id;
|
||||
}
|
||||
ConfigUtils.configureRulesEngine({ messageBroker: mb });
|
||||
if (diceFeatureConfiguration.enabled) {
|
||||
const rulesEngineConfig = ConfigUtils.getCurrentRulesEngineConfig();
|
||||
if (rulesEngineConfig.apiAdapter) {
|
||||
rulesEngineConfig.apiAdapter
|
||||
.get(`${diceFeatureConfiguration.apiEndpoint}${userConfigApi}`)
|
||||
.then((x) => {
|
||||
const diceCanvas = canvasElement;
|
||||
Dice.init({
|
||||
isDebug: false,
|
||||
assetBaseLocation: diceFeatureConfiguration.assetBaseLocation,
|
||||
trackingId: diceFeatureConfiguration.trackingId,
|
||||
sessionName: "Dice",
|
||||
notifier: new DiceNotifier(),
|
||||
canvas: diceCanvas || undefined,
|
||||
previewMode: false,
|
||||
diceUserConfig: ApiAdapterUtils.getResponseData(x) as any,
|
||||
})
|
||||
.then(() =>
|
||||
document.addEventListener("click", () => Dice.clear())
|
||||
)
|
||||
.catch((error: Error) => {
|
||||
AppLoggerUtils.logMessage(
|
||||
error.message,
|
||||
Constants.LogMessageType.WARNING
|
||||
);
|
||||
dispatch(
|
||||
appEnvActions.dataSet({
|
||||
diceEnabled: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch((error: ApiException) => {
|
||||
AppLoggerUtils.logMessage(
|
||||
error.message,
|
||||
Constants.LogMessageType.WARNING
|
||||
);
|
||||
dispatch(
|
||||
appEnvActions.dataSet({
|
||||
diceEnabled: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Dice.analyticsInit(diceFeatureConfiguration.trackingId, "Dice");
|
||||
}
|
||||
});
|
||||
}, [diceFeatureConfiguration, dispatch]);
|
||||
}, [
|
||||
campaign,
|
||||
diceFeatureConfiguration.apiEndpoint,
|
||||
diceFeatureConfiguration.assetBaseLocation,
|
||||
diceFeatureConfiguration.enabled,
|
||||
diceFeatureConfiguration.trackingId,
|
||||
dispatch,
|
||||
isSheet,
|
||||
user?.id,
|
||||
]);
|
||||
|
||||
if (isVttView) return null;
|
||||
|
||||
return ReactDOM.createPortal(
|
||||
<div className={"dice-rolling-panel"} ref={canvasContainer}>
|
||||
{canShow && diceEnabled && (
|
||||
<DiceToolbar
|
||||
rollContext={characterRollContext}
|
||||
rollTargetOptions={
|
||||
messageTargetOptions && isSheet
|
||||
? Object.values(messageTargetOptions?.entities).filter(
|
||||
TypeScriptUtils.isNotNullOrUndefined
|
||||
)
|
||||
: undefined
|
||||
<AnchoredPopover
|
||||
offset={16}
|
||||
open={isCustomDiceRollerOpen}
|
||||
allowedPlacements={["top-start"]}
|
||||
referenceComponent={
|
||||
<Button
|
||||
className={clsx([
|
||||
styles.button,
|
||||
isCustomDiceRollerOpen && styles.customDiceRollOpen,
|
||||
])}
|
||||
onClick={() => {
|
||||
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}
|
||||
>
|
||||
<D20 />
|
||||
</Button>
|
||||
}
|
||||
rollTargetDefault={defaultMessageTargetOption}
|
||||
themeColor={theme.themeColor}
|
||||
userId={parseInt(userId || "0", 10)}
|
||||
/>
|
||||
floatingArrow
|
||||
floatingArrowClassName={styles.floatingArrow}
|
||||
>
|
||||
{diceSets && (
|
||||
<CustomDiceRoller
|
||||
rollCallback={() => 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}
|
||||
/>
|
||||
)}
|
||||
</AnchoredPopover>
|
||||
)}
|
||||
{/* We want this one so it is sticking around,
|
||||
also this is where the canvas goes when we append */}
|
||||
|
||||
Reference in New Issue
Block a user