diff --git a/package.json b/package.json index 1b33106..8ddd945 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lingdocs/pashto-inflector", - "version": "2.6.8", + "version": "2.6.9", "author": "lingdocs.com", "description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations", "homepage": "https://verbs.lingdocs.com", diff --git a/src/components/ep-explorer/EPExplorer.tsx b/src/components/ep-explorer/EPExplorer.tsx index e912d97..0cf1453 100644 --- a/src/components/ep-explorer/EPExplorer.tsx +++ b/src/components/ep-explorer/EPExplorer.tsx @@ -13,6 +13,9 @@ import { completeEPSelection } from "../../lib/phrase-building/render-ep"; import { makeEPSBlocks, getSubjectSelection } from "../../lib/phrase-building/blocks-utils"; import APPicker from "../ap-picker/APPicker"; import autoAnimate from "@formkit/auto-animate"; +// @ts-ignore +import LZString from "lz-string"; +const phraseURLParam = "EPhrase"; const blankEps: T.EPSelectionState = { blocks: makeEPSBlocks(), @@ -37,10 +40,22 @@ function EPExplorer(props: { const [mode, setMode] = useStickyState<"charts" | "phrases">("charts", "EPExplorerMode"); const [eps, adjustEps] = useStickyReducer(epsReducer, blankEps, "EPState4", flashMessage); const [alert, setAlert] = useState(undefined); + const [showClipped, setShowClipped] = useState(""); const parent = useRef(null); useEffect(() => { parent.current && autoAnimate(parent.current); }, [parent]); + useEffect(() => { + const EPSFromUrl = getEPSFromUrl(); + if (EPSFromUrl) { + setMode("phrases"); + adjustEps({ + type: "load EPS", + payload: EPSFromUrl, + }); + } + // eslint-disable-next-line + }, []); const subject = getSubjectSelection(eps.blocks).selection; const king = subject?.type === "pronoun" ? "subject" @@ -53,9 +68,26 @@ function EPExplorer(props: { setAlert(undefined); }, 1500); } + function flashClippedMessage(m: string) { + setShowClipped(m); + setTimeout(() => { + setShowClipped(""); + }, 1250); + } + function handleCopyCode() { + const code = getCode(eps); + navigator.clipboard.writeText(code); + flashClippedMessage("Copied phrase code to clipboard"); + } + function handleCopyShareLink() { + const shareUrl = getShareUrl(eps); + navigator.clipboard.writeText(shareUrl); + flashClippedMessage("Copied phrase URL to clipboard"); + } const phraseIsComplete = !!completeEPSelection(eps); return
-
+
+
+
+
+ {(mode === "phrases" && phraseIsComplete) ? : ""} +
+
+ {mode === "phrases" ? : ""} +
+
{mode === "phrases" &&
adjustEps({ type: "insert new AP" })}>+ AP
}
@@ -160,7 +208,39 @@ function EPExplorer(props: { }}> {alert}
} + {showClipped &&
+ {showClipped} +
}
; } export default EPExplorer; + +function getShareUrl(eps: T.EPSelectionState): string { + const code = getCode(eps); + const encoded = LZString.compressToEncodedURIComponent(code); + const url = new URL(window.location.href); + // need to delete or else you could just get a second param written after + // which gets ignored + url.searchParams.delete(phraseURLParam); + url.searchParams.append(phraseURLParam, encoded); + return url.toString(); +} + +function getCode(eps: T.EPSelectionState): string { + return JSON.stringify(eps); +} + +function getEPSFromUrl(): T.EPSelectionState | undefined { + const params = new URLSearchParams(window.location.search); + const fromParams = params.get(phraseURLParam); + if (!fromParams) return; + const decoded = LZString.decompressFromEncodedURIComponent(fromParams); + return JSON.parse(decoded) as T.EPSelectionState; +} diff --git a/src/components/ep-explorer/eps-reducer.ts b/src/components/ep-explorer/eps-reducer.ts index f3e4fb2..c0c550e 100644 --- a/src/components/ep-explorer/eps-reducer.ts +++ b/src/components/ep-explorer/eps-reducer.ts @@ -42,7 +42,10 @@ type EpsReducerAction = { index: number, direction: "back" | "forward", }, -}; +} | { + type: "load EPS", + payload: T.EPSelectionState, +} export default function epsReducer(eps: T.EPSelectionState, action: EpsReducerAction, sendAlert?: (msg: string) => void): T.EPSelectionState { if (action.type === "set predicate type") { @@ -173,6 +176,9 @@ export default function epsReducer(eps: T.EPSelectionState, action: EpsReducerAc blocks: shiftBlock(eps.blocks, index, direction), }; } + if (action.type === "load EPS") { + return action.payload; + } throw new Error("unknown epsReducer action"); } diff --git a/src/components/vp-explorer/VPExplorer.tsx b/src/components/vp-explorer/VPExplorer.tsx index 6f779f3..184c9cd 100644 --- a/src/components/vp-explorer/VPExplorer.tsx +++ b/src/components/vp-explorer/VPExplorer.tsx @@ -20,7 +20,7 @@ import APPicker from "../ap-picker/APPicker"; import autoAnimate from "@formkit/auto-animate"; import { getObjectSelection, getSubjectSelection, isNoObject } from "../../lib/phrase-building/blocks-utils"; -const phraseURLParam = "VPPhrase"; +const phraseURLParam = "VPhrase"; // TODO: Issue with dynamic compounds english making with plurals // TODO: Issue with "the money were taken" @@ -55,7 +55,7 @@ function VPExplorer(props: { }, "verbExplorerMode2", ); - const [showShareClipped, setShowShareClipped] = useState(false); + const [showClipped, setShowClipped] = useState(""); const [alert, setAlert] = useState(undefined); const [showingExplanation, setShowingExplanation] = useState<{ role: "servant" | "king", item: "subject" | "object" } | false>(false); const parent = useRef(null); @@ -121,14 +121,22 @@ function VPExplorer(props: { payload: form, }); } + function flashClippedMessage(m: string) { + setShowClipped(m); + setTimeout(() => { + setShowClipped(""); + }, 1250); + } // for some crazy reason I can't get the URI share thing to encode and decode properly function handleCopyShareLink() { const shareUrl = getShareUrl(vps); navigator.clipboard.writeText(shareUrl); - setShowShareClipped(true); - setTimeout(() => { - setShowShareClipped(false); - }, 1250); + flashClippedMessage("Copied phrase URL to clipboard"); + } + function handleCopyCode() { + const code = getCode(vps); + navigator.clipboard.writeText(code); + flashClippedMessage("Copied phrase code to clipboard"); } const object = getObjectSelection(vps.blocks).selection; const subject = getSubjectSelection(vps.blocks).selection; @@ -160,12 +168,21 @@ function VPExplorer(props: { ]} handleChange={setMode} /> -
- {mode === "phrases" ? : ""} +
+
+ {(mode === "phrases" && phraseIsComplete) ? : ""} +
+
+ {mode === "phrases" ? : ""} +
{(vps.verb && (typeof object === "object") && (vps.verb.isCompound !== "dynamic") && (vps.verb.tenseCategory !== "imperative") &&(mode === "phrases")) && @@ -288,14 +305,14 @@ function VPExplorer(props: { showing={showingExplanation} setShowing={setShowingExplanation} /> - {showShareClipped &&
- Phrase URL copied to clipboard + {showClipped}
} {alert &&