import { PropsWithChildren, forwardRef, useEffect, useImperativeHandle, useState } from "react"; import { useTranslation } from "react-i18next"; import styled from "styled-components"; import Terria from "../../../../../Models/Terria"; import ViewState from "../../../../../ReactViewModels/ViewState"; import Spacing from "../../../../../Styled/Spacing"; import { TextSpan } from "../../../../../Styled/Text"; import { Category, ShareAction } from "../../../../../Core/Analytics/analyticEvents"; import Clipboard from "../../../../Clipboard"; import { buildShareLink, buildShortShareLink } from "../BuildShareLink"; import { ShareUrlWarning } from "./ShareUrlWarning"; import TerriaError, { TerriaErrorSeverity } from "../../../../../Core/TerriaError"; interface IShareUrlProps { terria: Terria; viewState: ViewState; includeStories: boolean; shouldShorten: boolean; callback?: () => void; } export interface IShareUrlRef { url: string; shorteningInProgress: boolean; } export const ShareUrl = forwardRef< IShareUrlRef, PropsWithChildren >(function ShareUrl( { terria, viewState, includeStories, shouldShorten, children, callback }, forwardRef ) { const { t } = useTranslation(); const [shareUrl, setShareUrl] = useState(""); const [shorteningInProgress, setShorteningInProgress] = useState(false); const [placeholder, setPlaceholder] = useState(); useImperativeHandle( forwardRef, () => ({ url: shareUrl, shorteningInProgress: shorteningInProgress }), /* eslint-disable-next-line react-hooks/exhaustive-deps */ [forwardRef, shareUrl, shorteningInProgress] ); useEffect(() => { let cancelled = false; if (shouldShorten) { setPlaceholder(t(($) => $.share.shortLinkShortening)); setShorteningInProgress(true); buildShortShareLink(terria, viewState, { includeStories }) .then((shareUrl) => { if (!cancelled) setShareUrl(shareUrl); }) .catch((error) => { let userMessage: string = t( ($) => $.models.shareData.generateErrorMessage ); if (error instanceof TerriaError) { const highestImportanceError = error.highestImportanceError; const highestImportanceOriginalErrorMessage = highestImportanceError.originalError?.[0].message; if (highestImportanceOriginalErrorMessage?.includes("413")) { userMessage = t( ($) => $.models.shareData.generateErrorDataExceedsLimitMessage ); terria.raiseErrorToUser( TerriaError.from(error, { message: userMessage }), { severity: TerriaErrorSeverity.Error } ); } } if (!cancelled) { setShareUrl(userMessage); } }) .finally(() => { if (!cancelled) setShorteningInProgress(false); }); } else { setShareUrl( buildShareLink(terria, viewState, { includeStories }) ); } return () => { cancelled = true; }; /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [terria, viewState, shouldShorten, includeStories]); const hasStory = includeStories && terria.stories && terria.stories.length; return ( <> {hasStory ? t(($) => $.clipboard.storyExplanation) : t(($) => $.clipboard.shareExplanation)} $.share.storyLinkCreated) : t(($) => $.share.shareLinkCreated) } onCopy={(text) => terria.analytics.logEvent(Category.share, ShareAction.storyCopy, text) } /> {children} {})} /> ); }); const Explanation = styled(TextSpan)` opacity: 0.8; `;