New source found from dndbeyond.com
This commit is contained in:
+100
-98
@@ -1,11 +1,12 @@
|
||||
// import axe from '@axe-core/react';
|
||||
import { css } from "@mui/material";
|
||||
import GlobalStyles from "@mui/material/GlobalStyles";
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import Modal from "react-modal";
|
||||
import { Provider } from "react-redux";
|
||||
import { useLocation, useMatch, useNavigate } from "react-router-dom";
|
||||
import { Store } from "redux";
|
||||
import { useStore } from "react-redux";
|
||||
import {
|
||||
useLocation,
|
||||
useMatch,
|
||||
useNavigate,
|
||||
useSearchParams,
|
||||
} from "react-router-dom";
|
||||
|
||||
import {
|
||||
characterEnvActions,
|
||||
@@ -15,16 +16,15 @@ import {
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import config from "~/config";
|
||||
import { useAuth } from "~/contexts/Authentication";
|
||||
import { CharacterThemeProvider } from "~/contexts/CharacterTheme";
|
||||
import { SidebarProvider } from "~/contexts/Sidebar";
|
||||
import useUserId from "~/hooks/useUserId";
|
||||
import useUserName from "~/hooks/useUserName";
|
||||
import useUserRoles from "~/hooks/useUserRoles";
|
||||
|
||||
import "../styles/styles.scss";
|
||||
import CharacterBuilderContainer from "./CharacterBuilder/containers/CharacterBuilderContainer";
|
||||
import CharacterSheetContainer from "./CharacterSheet/containers/CharacterSheetContainer";
|
||||
import configureSheetStore from "./CharacterSheet/store/configureStore";
|
||||
import { appEnvActions } from "./Shared/actions";
|
||||
import { Managers } from "./Shared/managers";
|
||||
import {
|
||||
@@ -52,9 +52,10 @@ export const SheetBuilderApp: React.FC<Props> = ({
|
||||
redirect,
|
||||
}) => {
|
||||
const username = useUserName();
|
||||
const userId = useUserId();
|
||||
const user = useAuth();
|
||||
const userRoles = useUserRoles();
|
||||
const navigate = useNavigate();
|
||||
const matchPremadePage = useMatch(`${BASE_PATHNAME}/premade/*`);
|
||||
const matchBuilderWithOutCharacter = useMatch(`${BASE_PATHNAME}/builder/*`);
|
||||
const matchBuilderWithCharacter = useMatch(
|
||||
`${BASE_PATHNAME}/:characterId/builder/*`
|
||||
@@ -64,6 +65,8 @@ export const SheetBuilderApp: React.FC<Props> = ({
|
||||
`${BASE_PATHNAME}/:characterId/:shareId`
|
||||
);
|
||||
const currentPath = useLocation().pathname;
|
||||
const [searchParams] = useSearchParams();
|
||||
const isVttView = searchParams.get("view") === "vtt";
|
||||
|
||||
if (config === undefined) {
|
||||
throw Error("Missing Config");
|
||||
@@ -71,7 +74,11 @@ export const SheetBuilderApp: React.FC<Props> = ({
|
||||
|
||||
let appContext: Constants.AppContextTypeEnum | null = null;
|
||||
switch (true) {
|
||||
case !!(matchBuilderWithOutCharacter || matchBuilderWithCharacter):
|
||||
case !!(
|
||||
matchBuilderWithOutCharacter ||
|
||||
matchBuilderWithCharacter ||
|
||||
matchPremadePage
|
||||
):
|
||||
appContext = Constants.AppContextTypeEnum.BUILDER;
|
||||
break;
|
||||
case !!(matchSheet || matchSheetWithShareId):
|
||||
@@ -93,11 +100,8 @@ export const SheetBuilderApp: React.FC<Props> = ({
|
||||
debug: appConfig.debug,
|
||||
});
|
||||
|
||||
let store: Store = configureSheetStore();
|
||||
store.dispatch({
|
||||
type: "SET_ROUTE_CONTROLS",
|
||||
payload: { navigate, currentPath },
|
||||
});
|
||||
const store = useStore();
|
||||
const initializedRef = React.useRef(false);
|
||||
|
||||
let parsedDiceEnabled: boolean = true;
|
||||
if (!diceFeatureConfiguration.enabled) {
|
||||
@@ -139,25 +143,54 @@ export const SheetBuilderApp: React.FC<Props> = ({
|
||||
canUseCurrencyContainers: true,
|
||||
});
|
||||
|
||||
store.dispatch(
|
||||
characterEnvActions.dataSet({
|
||||
context: appContext,
|
||||
})
|
||||
);
|
||||
// CharacterSheet.componentDidMount fires before parent useEffects, so characterId and
|
||||
// appContext must be in the store synchronously before children mount. Without this,
|
||||
// the character load saga reads a null characterId and the character fails to load.
|
||||
// The useEffect below handles re-dispatching once username/user resolve asynchronously.
|
||||
if (!initializedRef.current) {
|
||||
initializedRef.current = true;
|
||||
store.dispatch(
|
||||
characterEnvActions.dataSet({
|
||||
context: appContext,
|
||||
})
|
||||
);
|
||||
store.dispatch(
|
||||
appEnvActions.dataSet({
|
||||
username,
|
||||
userId: user?.id ? Number(user.id) : -1,
|
||||
userRoles,
|
||||
characterId,
|
||||
authEndpoint: config.authEndpoint,
|
||||
redirect,
|
||||
diceEnabled: parsedDiceEnabled,
|
||||
diceFeatureConfiguration: diceFeatureConfiguration,
|
||||
gameLog: gameLogSettings,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
store.dispatch(
|
||||
appEnvActions.dataSet({
|
||||
username,
|
||||
userId: userId ? Number(userId) : -1,
|
||||
userRoles,
|
||||
characterId,
|
||||
authEndpoint: config.authEndpoint,
|
||||
redirect,
|
||||
diceEnabled: parsedDiceEnabled,
|
||||
diceFeatureConfiguration: diceFeatureConfiguration,
|
||||
gameLog: gameLogSettings,
|
||||
})
|
||||
);
|
||||
useEffect(() => {
|
||||
store.dispatch({
|
||||
type: "SET_ROUTE_CONTROLS",
|
||||
payload: { navigate, currentPath },
|
||||
});
|
||||
}, [navigate, currentPath]);
|
||||
|
||||
useEffect(() => {
|
||||
store.dispatch(
|
||||
appEnvActions.dataSet({
|
||||
username,
|
||||
userId: user?.id ? Number(user.id) : -1,
|
||||
userRoles,
|
||||
characterId,
|
||||
authEndpoint: config.authEndpoint,
|
||||
redirect,
|
||||
diceEnabled: parsedDiceEnabled,
|
||||
diceFeatureConfiguration: diceFeatureConfiguration,
|
||||
gameLog: gameLogSettings,
|
||||
})
|
||||
);
|
||||
}, [username, user]);
|
||||
|
||||
// Setup axe-core in development, not in production
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
@@ -165,70 +198,39 @@ export const SheetBuilderApp: React.FC<Props> = ({
|
||||
}
|
||||
|
||||
Modal.setAppElement("#character-tools-target");
|
||||
|
||||
// If the view is the VTT view, set --top-navigation-height to 0 because the top nav will not be present.
|
||||
useEffect(() => {
|
||||
if (isVttView) {
|
||||
document.body.style.setProperty("--top-navigation-height", "0px");
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<Managers>
|
||||
<CharacterThemeProvider>
|
||||
<SidebarProvider>
|
||||
<GlobalStyles
|
||||
styles={() => {
|
||||
return css`
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
textarea {
|
||||
font-family: Roboto, Helvetica, sans-serif;
|
||||
font-size: 100%;
|
||||
margin: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
input[type="search"],
|
||||
input[type="password"],
|
||||
input[type="email"],
|
||||
textarea,
|
||||
select {
|
||||
background-color: #fff;
|
||||
background: #fff none;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
color: #000;
|
||||
padding: 4px;
|
||||
transition: 0.2s linear border, 0.2s linear box-shadow;
|
||||
}
|
||||
|
||||
input[type="text"]:focus,
|
||||
input[type="number"]:focus,
|
||||
input[type="search"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="email"]:focus,
|
||||
textarea:focus {
|
||||
border-color: #242527;
|
||||
box-shadow: 0 0 4px rgba(36, 37, 39, 0.6);
|
||||
background-color: #f9f9f9;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
button,
|
||||
input[type="button"],
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
}}
|
||||
/>
|
||||
{matchBuilderWithOutCharacter || matchBuilderWithCharacter ? (
|
||||
<CharacterBuilderContainer />
|
||||
) : (
|
||||
<CharacterSheetContainer authEndpoint={config.authEndpoint} />
|
||||
)}
|
||||
</SidebarProvider>
|
||||
</CharacterThemeProvider>
|
||||
</Managers>
|
||||
</Provider>
|
||||
<Managers>
|
||||
<CharacterThemeProvider>
|
||||
<Content />
|
||||
</CharacterThemeProvider>
|
||||
</Managers>
|
||||
);
|
||||
};
|
||||
|
||||
const Content = () => {
|
||||
const matchBuilderWithOutCharacter = useMatch(`${BASE_PATHNAME}/builder/*`);
|
||||
const matchBuilderWithCharacter = useMatch(
|
||||
`${BASE_PATHNAME}/:characterId/builder/*`
|
||||
);
|
||||
const matchPremadePage = useMatch(`${BASE_PATHNAME}/premade/*`);
|
||||
|
||||
return (
|
||||
<SidebarProvider>
|
||||
{matchBuilderWithOutCharacter ||
|
||||
matchBuilderWithCharacter ||
|
||||
matchPremadePage ? (
|
||||
<CharacterBuilderContainer isPremadeListing={!!matchPremadePage} />
|
||||
) : (
|
||||
<CharacterSheetContainer authEndpoint={config.authEndpoint} />
|
||||
)}
|
||||
</SidebarProvider>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user