import classNames from "classnames"; import "inobounce"; import { action } from "mobx"; import { observer } from "mobx-react"; import { FC, DragEvent, ReactNode, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { DefaultTheme } from "styled-components"; import combine from "terriajs-cesium/Source/Core/combine"; import ViewState from "../../ReactViewModels/ViewState"; import Disclaimer from "../Disclaimer"; import DragDropFile from "../DragDropFile"; import ExplorerWindow from "../ExplorerWindow/ExplorerWindow"; import FeatureInfoPanel from "../FeatureInfo/FeatureInfoPanel"; import FeedbackForm from "../Feedback/FeedbackForm"; import { Medium, Small } from "../Generic/Responsive"; import SatelliteHelpPrompt from "../HelpScreens/SatelliteHelpPrompt"; import withFallback from "../HOCs/withFallback"; import ExperimentalFeatures from "./ExperimentalFeatures"; import { CollapsedNavigation } from "../Map/MapNavigation"; import HelpPanel from "../Map/Panels/HelpPanel/HelpPanel"; import PrintView from "../Map/Panels/SharePanel/Print/PrintView"; import TrainerBar from "./TrainerBar/TrainerBar"; import MobileHeader from "../Mobile/MobileHeader"; import MapInteractionWindow from "../Notification/MapInteractionWindow"; import Notification from "../Notification/Notification"; import Branding from "../SidePanel/Branding"; import FullScreenButton from "../SidePanel/FullScreenButton"; import SidePanel from "../SidePanel/SidePanel"; import StoryBuilder from "../Story/StoryBuilder"; import StoryPanel from "../Story/StoryPanel/StoryPanel"; import ClippingBoxToolLauncher from "../Tools/ClippingBox/ClippingBoxToolLauncher"; import Tool from "../Tools/Tool"; import TourPortal from "../Tour/TourPortal"; import WelcomeMessage from "../WelcomeMessage/WelcomeMessage"; import SelectableDimensionWorkflow from "../Workflow/SelectableDimensionWorkflow"; import WorkflowPanelPortal from "../Workflow/WorkflowPanelPortal"; import { ContextProviders } from "../Context"; import { GlobalTerriaStyles } from "./GlobalTerriaStyles"; import MapColumn from "../Map/MapColumn"; import processCustomElements from "./processCustomElements"; import SidePanelContainer from "./SidePanelContainer"; import Styles from "./standard-user-interface.scss"; import { terriaTheme } from "./StandardTheme"; export const animationDuration = 250; interface StandardUserInterfaceProps { terria: ViewState["terria"]; viewState: ViewState; themeOverrides?: Partial; minimumLargeScreenWidth?: number; version: string; children?: ReactNode; } const StandardUserInterfaceBase: FC = observer( (props) => { const { t } = useTranslation(); const acceptDragDropFile = action(() => { props.viewState.isDraggingDroppingFile = true; // if explorer window is already open, we open my data tab if (props.viewState.explorerPanelIsVisible) { props.viewState.openUserData(); } }); const handleDragOver = (e: DragEvent) => { if (!e.dataTransfer.types || !e.dataTransfer.types.includes("Files")) { return; } e.preventDefault(); e.stopPropagation(); e.dataTransfer.dropEffect = "copy"; acceptDragDropFile(); }; const shouldUseMobileInterface = () => document.body.clientWidth < (props.minimumLargeScreenWidth ?? 768); const resizeListener = action(() => { props.viewState.useSmallScreenInterface = shouldUseMobileInterface(); }); useEffect(() => { window.addEventListener("resize", resizeListener, false); return () => { window.removeEventListener("resize", resizeListener, false); }; /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, []); /* eslint-disable-next-line react-hooks/exhaustive-deps */ useEffect(resizeListener, [props.minimumLargeScreenWidth]); useEffect(() => { if ( props.terria.configParameters.storyEnabled && props.terria.stories && props.terria.stories.length && !props.viewState.storyShown ) { props.terria.notificationState.addNotificationToQueue({ title: t("sui.notifications.title"), message: t("sui.notifications.message"), confirmText: t("sui.notifications.confirmText"), denyText: t("sui.notifications.denyText"), confirmAction: action(() => { props.viewState.storyShown = true; }), denyAction: action(() => { props.viewState.storyShown = false; }), type: "story", width: 300 }); } /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [props.terria.storyPromptShown]); // Merge theme in order of highest priority: themeOverrides props -> theme config parameter -> default terriaTheme const mergedTheme = combine( props.themeOverrides, combine(props.terria.configParameters.theme, terriaTheme, true), true ); const theme = mergedTheme; const customElements = processCustomElements( props.viewState.useSmallScreenInterface, props.children ); const showStoryBuilder = props.viewState.storyBuilderShown && !props.viewState.useSmallScreenInterface; const showStoryPanel = props.terria.configParameters.storyEnabled && props.terria.stories.length > 0 && props.viewState.storyShown && !props.viewState.explorerPanelIsVisible && !props.viewState.storyBuilderShown; return (
{!props.viewState.disclaimerVisible && }
{!props.viewState.hideMapUi && ( <> <> )}
{props.terria.configParameters.experimentalFeatures && !props.viewState.hideMapUi && ( )}
{!props.viewState.hideMapUi && ( )} {/* I think this does what the previous boolean condition does, but without the console error */} {props.viewState.isToolOpen && ( )} {props.viewState.panel} {!customElements.feedback.length && props.terria.configParameters.feedbackUrl && !props.viewState.hideMapUi && props.viewState.feedbackFormIsVisible && }
{ props.viewState.topElement = "FeatureInfo"; })} >
{showStoryPanel && (
{ props.viewState.topElement = "StoryPanel"; })} >
)}
{props.terria.configParameters.storyEnabled && showStoryBuilder && ( )} {props.viewState.showHelpMenu && props.viewState.topElement === "HelpPanel" && }
{props.viewState.printWindow && ( props.viewState.setPrintWindow(null)} /> )}
); } ); export const StandardUserInterface = withFallback(StandardUserInterfaceBase); export default withFallback(StandardUserInterfaceBase);