Change how customizer params are applied #529

Merged
Irev-Dev merged 3 commits from kurt/customizer-tweaks into main 2021-09-27 22:05:22 +02:00
5 changed files with 62 additions and 19 deletions

View File

@@ -14,12 +14,23 @@ import {
} from './customizerConverter' } from './customizerConverter'
const Customizer = () => { const Customizer = () => {
const [open, setOpen] = React.useState(false)
const [shouldLiveUpdate, setShouldLiveUpdate] = React.useState(false) const [shouldLiveUpdate, setShouldLiveUpdate] = React.useState(false)
const { state, thunkDispatch } = useIdeContext() const { state, thunkDispatch } = useIdeContext()
const isOpen = state.isCustomizerOpen
const customizerParams = state?.customizerParams const customizerParams = state?.customizerParams
const currentParameters = state?.currentParameters || {} const currentParameters = state?.currentParameters || {}
const handleRender = useRender() const handleRender = useRender()
const toggleOpen = () => {
thunkDispatch({ type: 'setCustomizerOpenState', payload: !isOpen })
if (state.viewerContext === 'ide') {
// don't re-render on open/close in the project profile
setTimeout(() => handleRender())
}
}
const handleReset = () => {
thunkDispatch({ type: 'resetCustomizer' })
setTimeout(() => handleRender(true))
}
const updateCustomizerParam = (paramName: string, paramValue: any) => { const updateCustomizerParam = (paramName: string, paramValue: any) => {
const payload = { const payload = {
@@ -33,20 +44,20 @@ const Customizer = () => {
return ( return (
<div <div
className={`absolute inset-x-0 bottom-0 bg-ch-gray-600 bg-opacity-60 text-ch-gray-300 text-lg font-fira-sans ${ className={`absolute inset-x-0 bottom-0 bg-ch-gray-600 bg-opacity-60 text-ch-gray-300 text-lg font-fira-sans ${
open ? 'h-full max-h-96' : '' isOpen ? 'h-full max-h-96' : ''
}`} }`}
> >
<div className="flex justify-between px-6 py-2 items-center"> <div className="flex justify-between px-6 py-2 items-center">
<div className="grid grid-flow-col-dense gap-6 items-center"> <div className="grid grid-flow-col-dense gap-6 items-center">
<button className="px-2" onClick={() => setOpen(!open)}> <button className="px-2" onClick={toggleOpen}>
<Svg <Svg
name="chevron-down" name="chevron-down"
className={`h-8 w-8 ${!open && 'transform rotate-180'}`} className={`h-8 w-8 ${!isOpen && 'transform rotate-180'}`}
/> />
</button> </button>
<div>Parameters</div> <div>Parameters</div>
</div> </div>
{open && ( {isOpen && (
<> <>
<div className="flex items-center"> <div className="flex items-center">
<div className="font-fira-sans text-sm mr-4">Auto Update</div> <div className="font-fira-sans text-sm mr-4">Auto Update</div>
@@ -66,11 +77,17 @@ const Customizer = () => {
} inline-block w-4 h-4 transform bg-white rounded-full`} } inline-block w-4 h-4 transform bg-white rounded-full`}
/> />
</Switch> </Switch>
<button
className="px-4 py-1 rounded bg-ch-gray-300 text-ch-gray-600 mr-2"
onClick={handleReset}
>
Reset
</button>
<button <button
className={`px-4 py-1 rounded bg-ch-gray-300 text-ch-gray-800 ${ className={`px-4 py-1 rounded bg-ch-gray-300 text-ch-gray-800 ${
shouldLiveUpdate && 'bg-opacity-30 cursor-default' shouldLiveUpdate && 'bg-opacity-30 cursor-default'
}`} }`}
onClick={handleRender} onClick={() => handleRender()}
disabled={shouldLiveUpdate} disabled={shouldLiveUpdate}
> >
Update Update
@@ -79,7 +96,9 @@ const Customizer = () => {
</> </>
)} )}
</div> </div>
<div className={`${open ? 'h-full pb-32' : 'h-0'} overflow-y-auto px-12`}> <div
className={`${isOpen ? 'h-full pb-32' : 'h-0'} overflow-y-auto px-12`}
>
<div> <div>
{customizerParams.map((param, index) => { {customizerParams.map((param, index) => {
const otherProps = { const otherProps = {

View File

@@ -5,6 +5,7 @@ import { useIdeContext } from 'src/helpers/hooks/useIdeContext'
import { useRender } from 'src/components/IdeWrapper/useRender' import { useRender } from 'src/components/IdeWrapper/useRender'
import { encode, decode } from 'src/helpers/compress' import { encode, decode } from 'src/helpers/compress'
import { isBrowser } from '@redwoodjs/prerender/browserUtils' import { isBrowser } from '@redwoodjs/prerender/browserUtils'
import type { State } from 'src/helpers/hooks/useIdeState'
const scriptKey = 'encoded_script' const scriptKey = 'encoded_script'
const scriptKeyV2 = 'encoded_script_v2' const scriptKeyV2 = 'encoded_script_v2'
@@ -32,13 +33,17 @@ export function makeExternalUrl(resourceUrl: string): string {
}#${fetchText}=${prepareDecodedUrl(resourceUrl)}` }#${fetchText}=${prepareDecodedUrl(resourceUrl)}`
} }
export function useIdeInit(cadPackage: string, code = '') { export function useIdeInit(
cadPackage: State['ideType'],
code = '',
viewerContext: State['viewerContext'] = 'ide'
) {
const { thunkDispatch } = useIdeContext() const { thunkDispatch } = useIdeContext()
const handleRender = useRender() const handleRender = useRender()
useEffect(() => { useEffect(() => {
thunkDispatch({ thunkDispatch({
type: 'initIde', type: 'initIde',
payload: { cadPackage, code }, payload: { cadPackage, code, viewerContext },
}) })
if (code) { if (code) {
return return

View File

@@ -3,7 +3,7 @@ import { useIdeContext } from 'src/helpers/hooks/useIdeContext'
export const useRender = () => { export const useRender = () => {
const { state, thunkDispatch } = useIdeContext() const { state, thunkDispatch } = useIdeContext()
return () => { return (disableParams = false) => {
thunkDispatch((dispatch, getState) => { thunkDispatch((dispatch, getState) => {
const state = getState() const state = getState()
dispatch({ type: 'setLoading' }) dispatch({ type: 'setLoading' })
@@ -13,7 +13,7 @@ export const useRender = () => {
code: state.code, code: state.code,
viewerSize: state.viewerSize, viewerSize: state.viewerSize,
camera: state.camera, camera: state.camera,
parameters: state.currentParameters, parameters: disableParams ? {} : state.currentParameters,
}) })
}) })
localStorage.setItem(makeCodeStoreKey(state.ideType), state.code) localStorage.setItem(makeCodeStoreKey(state.ideType), state.code)

View File

@@ -1,4 +1,4 @@
import { useState, useEffect, useRef, lazy, Suspense } from 'react' import { useState, useEffect, useRef } from 'react'
import { useAuth } from '@redwoodjs/auth' import { useAuth } from '@redwoodjs/auth'
import { Link, navigate, routes } from '@redwoodjs/router' import { Link, navigate, routes } from '@redwoodjs/router'
import Editor from 'rich-markdown-editor' import Editor from 'rich-markdown-editor'
@@ -15,7 +15,6 @@ import CadPackage from 'src/components/CadPackage/CadPackage'
import Gravatar from 'src/components/Gravatar/Gravatar' import Gravatar from 'src/components/Gravatar/Gravatar'
import { useIdeInit } from 'src/components/EncodedUrl/helpers' import { useIdeInit } from 'src/components/EncodedUrl/helpers'
import ProfileViewer from '../ProfileViewer/ProfileViewer' import ProfileViewer from '../ProfileViewer/ProfileViewer'
import Svg from 'src/components/Svg/Svg'
import OpenscadStaticImageMessage from 'src/components/OpenscadStaticImageMessage/OpenscadStaticImageMessage' import OpenscadStaticImageMessage from 'src/components/OpenscadStaticImageMessage/OpenscadStaticImageMessage'
import KeyValue from 'src/components/KeyValue/KeyValue' import KeyValue from 'src/components/KeyValue/KeyValue'
@@ -51,7 +50,7 @@ const ProjectProfile = ({
}) })
) )
}, [currentUser]) }, [currentUser])
useIdeInit(project?.cadPackage, project?.code) useIdeInit(project?.cadPackage, project?.code, 'viewer')
const [newDescription, setNewDescription] = useState(project?.description) const [newDescription, setNewDescription] = useState(project?.description)
const onDescriptionChange = (description) => setNewDescription(description()) const onDescriptionChange = (description) => setNewDescription(description())
const onEditSaveClick = () => { const onEditSaveClick = () => {

View File

@@ -33,6 +33,7 @@ interface EditorModel {
export interface State { export interface State {
ideType: 'INIT' | CadPackageType ideType: 'INIT' | CadPackageType
viewerContext: 'ide' | 'viewer'
ideGuide?: string ideGuide?: string
consoleMessages: { type: 'message' | 'error'; message: string; time: Date }[] consoleMessages: { type: 'message' | 'error'; message: string; time: Date }[]
code: string code: string
@@ -45,6 +46,7 @@ export interface State {
} }
customizerParams: CadhubParams[] customizerParams: CadhubParams[]
currentParameters?: RawCustomizerParams currentParameters?: RawCustomizerParams
isCustomizerOpen: boolean
layout: any layout: any
camera: { camera: {
dist?: number dist?: number
@@ -71,6 +73,7 @@ const initialLayout = {
export const initialState: State = { export const initialState: State = {
ideType: 'INIT', ideType: 'INIT',
viewerContext: 'ide',
consoleMessages: [ consoleMessages: [
{ type: 'message', message: 'Initialising', time: new Date() }, { type: 'message', message: 'Initialising', time: new Date() },
], ],
@@ -83,6 +86,7 @@ export const initialState: State = {
quality: 'low', quality: 'low',
}, },
customizerParams: [], customizerParams: [],
isCustomizerOpen: false,
layout: initialLayout, layout: initialLayout,
camera: {}, camera: {},
viewerSize: { width: 0, height: 0 }, viewerSize: { width: 0, height: 0 },
@@ -103,17 +107,28 @@ const reducer = (state: State, { type, payload }): State => {
'', '',
ideType: payload.cadPackage, ideType: payload.cadPackage,
ideGuide: initGuideMap[payload.cadPackage], ideGuide: initGuideMap[payload.cadPackage],
viewerContext: payload.viewerContext,
} }
case 'updateCode': case 'updateCode':
return { ...state, code: payload } return { ...state, code: payload }
case 'resetCustomizer':
const resetParameters = {}
state.customizerParams.forEach(({ name, initial }) => {
resetParameters[name] = initial
})
return {
...state,
currentParameters: resetParameters,
}
case 'healthyRender': case 'healthyRender':
const customizerParams: CadhubParams[] = payload.customizerParams || []
const currentParameters = {} const currentParameters = {}
const customizerParams: CadhubParams[] = payload.customizerParams || []
customizerParams.forEach((param) => { customizerParams.forEach((param) => {
currentParameters[param.name] = currentParameters[param.name] =
typeof state?.currentParameters?.[param.name] !== 'undefined' typeof state?.currentParameters?.[param.name] === 'undefined'
? state?.currentParameters?.[param.name] ? param.initial
: param.initial : state?.currentParameters?.[param.name]
}) })
return { return {
...state, ...state,
@@ -143,6 +158,11 @@ const reducer = (state: State, { type, payload }): State => {
...state, ...state,
currentParameters: payload, currentParameters: payload,
} }
case 'setCustomizerOpenState':
return {
...state,
isCustomizerOpen: payload,
}
case 'setLayout': case 'setLayout':
return { return {
...state, ...state,
@@ -290,7 +310,7 @@ export const requestRender = ({
return renderFn({ return renderFn({
code, code,
settings: { settings: {
parameters, parameters: state.isCustomizerOpen ? parameters : {},
camera, camera,
viewerSize, viewerSize,
quality, quality,