feat: feature/mvp-sprint-1 Added loading check for localStorage thingtime, to be replaced by server-side rendering

This commit is contained in:
Nikolaj Frey 2023-08-08 08:05:07 +10:00
parent 9aa463bc48
commit f7b690b9ae
4 changed files with 75 additions and 46 deletions

View File

@ -53,6 +53,7 @@ const initialValues = {
}, },
} }
// const initialThingtime = createInitialThingtime()
const initialThingtime = smarts.merge(initialValues, force) const initialThingtime = smarts.merge(initialValues, force)
// TODO: Make localStorage be loaded first before initialValues if local version exists // TODO: Make localStorage be loaded first before initialValues if local version exists
@ -83,17 +84,20 @@ const initialThingtime = smarts.merge(initialValues, force)
// console.error("Caught error restoring thingtime from localstorage", err) // console.error("Caught error restoring thingtime from localstorage", err)
// } // }
// initialise thingtime
initialThingtime.thingtime = initialThingtime initialThingtime.thingtime = initialThingtime
initialThingtime.tt = initialThingtime initialThingtime.tt = initialThingtime
export const ThingtimeProvider = (props: any): JSX.Element => { export const ThingtimeProvider = (props: any): JSX.Element => {
const [thingtime, rawSet] = React.useState(initialThingtime) const [thingtime, rawSet] = React.useState()
const thingtimeRef = React.useRef(thingtime) const thingtimeRef = React.useRef(thingtime)
const stateRef = React.useRef({ const stateRef = React.useRef({
c: 1, c: 1,
}) })
const [loading, setLoading] = React.useState(true)
const set = React.useCallback((newThingtime) => { const set = React.useCallback((newThingtime) => {
const thingtimeReference = { const thingtimeReference = {
...newThingtime, ...newThingtime,
@ -218,7 +222,6 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
const thingtimeFromLocalStorage = window.localStorage.getItem("thingtime") const thingtimeFromLocalStorage = window.localStorage.getItem("thingtime")
console.log("nik thingtimeFromLocalStorage", thingtimeFromLocalStorage) console.log("nik thingtimeFromLocalStorage", thingtimeFromLocalStorage)
if (thingtimeFromLocalStorage) { if (thingtimeFromLocalStorage) {
const parsed = parse(thingtimeFromLocalStorage) const parsed = parse(thingtimeFromLocalStorage)
if (parsed) { if (parsed) {
@ -238,10 +241,14 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
console.log("nik localIsValid", localIsValid) console.log("nik localIsValid", localIsValid)
set(newThingtime) set(newThingtime)
} }
} else {
console.log("nik setting initialThingtime", initialThingtime)
set(initialThingtime)
} }
} catch (err) { } catch (err) {
console.error("There was an error getting thingtime from localStorage") console.error("There was an error getting thingtime from localStorage")
} }
setLoading(false)
}, []) }, [])
// thingtime change listener // thingtime change listener
@ -299,6 +306,7 @@ export const ThingtimeProvider = (props: any): JSX.Element => {
getThingtime, getThingtime,
thingtimeRef, thingtimeRef,
paths, paths,
loading,
} }
return ( return (

View File

@ -2,6 +2,7 @@ import React from "react"
import ContentEditable from "react-contenteditable" import ContentEditable from "react-contenteditable"
import { import {
Box, Box,
Center,
Flex, Flex,
Input, Input,
NumberDecrementStepper, NumberDecrementStepper,
@ -10,6 +11,7 @@ import {
NumberInputField, NumberInputField,
NumberInputStepper, NumberInputStepper,
Select, Select,
Spinner,
Switch, Switch,
Textarea, Textarea,
} from "@chakra-ui/react" } from "@chakra-ui/react"
@ -23,10 +25,12 @@ export const Thingtime = (props) => {
// and add button to expand circular reference // and add button to expand circular reference
// up to 1 level deep // up to 1 level deep
const { thingtime, setThingtime } = useThingtime() const { thingtime, setThingtime, loading } = useThingtime()
const [uuid, setUuid] = React.useState() const [uuid, setUuid] = React.useState()
const [root, setRoot] = React.useState(props?.notRoot ? false : true)
const [circular, setCircular] = React.useState(props?.circular) const [circular, setCircular] = React.useState(props?.circular)
const contentEditableRef = React.useRef(null) const contentEditableRef = React.useRef(null)
@ -172,9 +176,10 @@ export const Thingtime = (props) => {
const thingtimeChildren = React.useMemo(() => { const thingtimeChildren = React.useMemo(() => {
if (template1Modes?.includes(mode)) { if (template1Modes?.includes(mode)) {
if (keys?.length && !circular) { if (keys?.length && !circular) {
return ( const ret = (
<Safe {...props}> <Safe {...props}>
<Flex <Flex
className="nested-things"
position="relative" position="relative"
flexDirection="column" flexDirection="column"
// w={'500px'} // w={'500px'}
@ -208,6 +213,7 @@ export const Thingtime = (props) => {
circular={seen?.includes?.(nextThing)} circular={seen?.includes?.(nextThing)}
depth={depth + 1} depth={depth + 1}
parent={thing} parent={thing}
notRoot
fullPath={fullPath + "." + key?.key} fullPath={fullPath + "." + key?.key}
path={key} path={key}
thing={nextThing} thing={nextThing}
@ -219,6 +225,8 @@ export const Thingtime = (props) => {
</Flex> </Flex>
</Safe> </Safe>
) )
console.log("nik root ret", ret)
return ret
} }
} }
}, [ }, [
@ -226,6 +234,7 @@ export const Thingtime = (props) => {
mode, mode,
circular, circular,
seen, seen,
type,
fullPath, fullPath,
depth, depth,
thing, thing,
@ -236,14 +245,13 @@ export const Thingtime = (props) => {
template1Modes, template1Modes,
]) ])
const AtomicWrapper = React.useCallback( const AtomicWrapper = React.useCallback((props) => {
(props) => {
return ( return (
<Flex <Flex
flexDirection="row" flexDirection="row"
flexShrink={1} flexShrink={1}
width="100%" width="100%"
paddingLeft={pl} paddingLeft={props?.pl || props?.paddingLeft}
fontSize="20px" fontSize="20px"
border="none" border="none"
whiteSpace="pre-line" whiteSpace="pre-line"
@ -254,9 +262,7 @@ export const Thingtime = (props) => {
{props?.children} {props?.children}
</Flex> </Flex>
) )
}, }, [])
[pl]
)
const [contentEditableThing, setContentEditableThing] = React.useState(thing) const [contentEditableThing, setContentEditableThing] = React.useState(thing)
@ -276,13 +282,13 @@ export const Thingtime = (props) => {
const newlineClonePart1 = newlineClone?.replace( const newlineClonePart1 = newlineClone?.replace(
"\n\n\n", "\n\n\n",
"<div><br></div>" "<div><br /></div>"
) )
const newlineClonePart2 = newlineClonePart1?.replace( const newlineClonePart2 = newlineClonePart1?.replace(
/\n\n/g, /\n\n/g,
"<div><br></div>" "<div><br /></div>"
) )
const newlineClonePart3 = newlineClonePart2?.replace(/\n/g, "<br>") const newlineClonePart3 = newlineClonePart2?.replace(/\n/g, "<br />")
newValue = newValue?.replace(newline, newlineClonePart3) newValue = newValue?.replace(newline, newlineClonePart3)
}) })
@ -304,7 +310,7 @@ export const Thingtime = (props) => {
delete editValueRef.current[time] delete editValueRef.current[time]
} }
} }
}, [props?.thing]) }, [props?.thing, updateContentEditableThing])
const updateValue = React.useCallback( const updateValue = React.useCallback(
(args) => { (args) => {
@ -319,7 +325,7 @@ export const Thingtime = (props) => {
if (props?.edit) { if (props?.edit) {
if (type === "boolean") { if (type === "boolean") {
return ( return (
<AtomicWrapper> <AtomicWrapper paddingLeft={pl} className="boolean-atomic-wrapper">
<Box <Box
onClick={(e) => { onClick={(e) => {
e?.preventDefault?.() e?.preventDefault?.()
@ -339,8 +345,9 @@ export const Thingtime = (props) => {
if (type === "number") { if (type === "number") {
const numberPxLength = thing?.toString()?.length * 13 + 30 const numberPxLength = thing?.toString()?.length * 13 + 30
return ( return (
<AtomicWrapper> <AtomicWrapper paddingLeft={pl} className="number-atomic-wrapper">
<Flex> <Flex>
This is a number?
<NumberInput <NumberInput
alignItems="center" alignItems="center"
justifyContent="center" justifyContent="center"
@ -373,7 +380,7 @@ export const Thingtime = (props) => {
} }
if (type === "string" && typeof contentEditableThing === "string") { if (type === "string" && typeof contentEditableThing === "string") {
return ( return (
<AtomicWrapper> <AtomicWrapper paddingLeft={pl} className="string-atomic-wrapper">
<Box <Box
ref={contentEditableRef} ref={contentEditableRef}
width="100%" width="100%"
@ -394,11 +401,16 @@ export const Thingtime = (props) => {
) )
} }
} }
return <AtomicWrapper>{renderableValue}</AtomicWrapper>
return (
<AtomicWrapper paddingLeft={pl} className="default-atomic-wrapper">
{renderableValue}
</AtomicWrapper>
)
}, [ }, [
renderableValue,
contentEditableThing, contentEditableThing,
AtomicWrapper, renderableValue,
pl,
type, type,
props?.edit, props?.edit,
thing, thing,
@ -485,7 +497,8 @@ export const Thingtime = (props) => {
// minW={depth === 1 ? '120px' : null} // minW={depth === 1 ? '120px' : null}
paddingY={3} paddingY={3}
{...(props.chakras || {})} {...(props.chakras || {})}
className={`thing-${uuid?.current}`} className={`thing uuid-${uuid?.current}`}
data-path={props?.path}
> >
{/* {uuid?.current} */} {/* {uuid?.current} */}
<Flex position="relative" flexDirection="row"> <Flex position="relative" flexDirection="row">
@ -521,8 +534,12 @@ export const Thingtime = (props) => {
</Flex> </Flex>
</Flex> </Flex>
{/* {showContextMenu && contextMenu} */} {/* {showContextMenu && contextMenu} */}
{!thingtimeChildren && atomicValue} {!loading && !thingtimeChildren && atomicValue && (
{thingtimeChildren} <Box className="atomicValue">{atomicValue}</Box>
)}
{!loading && thingtimeChildren && (
<Box className="thingtimeChildren">{thingtimeChildren}</Box>
)}
</Flex> </Flex>
</Safe> </Safe>
) )

View File

@ -1,4 +1,4 @@
export const safe = props => { export const safe = (props) => {
// do not render more than the limit of things to prevent infinite loops // do not render more than the limit of things to prevent infinite loops
const thingtime = getThingtime() const thingtime = getThingtime()
@ -6,24 +6,24 @@ export const safe = props => {
try { try {
if ( if (
typeof thingtime?.things?.count === 'number' && typeof thingtime?.things?.count === "number" &&
thingtime?.things?.count >= thingtime?.things?.limit thingtime?.things?.count >= thingtime?.things?.limit
) { ) {
console.error( console.error(
'[codex] Maximum things reached', "[codex] Maximum things reached",
thingtime?.things?.count, thingtime?.things?.count,
thingtime?.things?.limit thingtime?.things?.limit
) )
return null return null
} }
} catch (err) { } catch (err) {
console.error('[codex] Error in Thingtime.tsx checking maximum things', err) console.error("[codex] Error in Thingtime.tsx checking maximum things", err)
} }
try { try {
if (!thingtime?.things?.db?.[uuid]) { if (!thingtime?.things?.db?.[uuid]) {
thingtime.things.db[uuid] = { thingtime.things.db[uuid] = {
count: 1 count: 1,
} }
thingtime.things.count++ thingtime.things.count++
} }
@ -34,7 +34,7 @@ export const safe = props => {
try { try {
if (props?.depth >= thingtime?.things?.maxDepth) { if (props?.depth >= thingtime?.things?.maxDepth) {
console.error( console.error(
'[codex] Reached max depth', "[codex] Reached max depth",
props?.depth, props?.depth,
thingtime?.things?.maxDepth thingtime?.things?.maxDepth
) )
@ -44,7 +44,11 @@ export const safe = props => {
// nothing // nothing
} }
try {
return props?.children return props?.children
} catch (err) {
console.error("Caught error returning children safely", err)
}
} }
export const getThingtime = () => { export const getThingtime = () => {

View File

@ -26,7 +26,7 @@ export default function Index() {
width="600px" width="600px"
path="Content" path="Content"
valuePl={0} valuePl={0}
thing={thingtime["Content"]} thing={thingtime?.["Content"]}
></Thingtime> ></Thingtime>
<ThingtimeDemo></ThingtimeDemo> <ThingtimeDemo></ThingtimeDemo>
<Thingtime <Thingtime