diff --git a/editor/src/components/canvas/controls/grid-controls.tsx b/editor/src/components/canvas/controls/grid-controls.tsx index 1b881e001dc0..9f23bff592dd 100644 --- a/editor/src/components/canvas/controls/grid-controls.tsx +++ b/editor/src/components/canvas/controls/grid-controls.tsx @@ -58,7 +58,6 @@ import { when } from '../../../utils/react-conditionals' import { useColorTheme, UtopiaStyles } from '../../../uuiui' import { useDispatch } from '../../editor/store/dispatch-context' import { Substores, useEditorState, useRefEditorState } from '../../editor/store/store-hook' -import { useRollYourOwnFeatures } from '../../navigator/left-pane/roll-your-own-pane' import CanvasActions from '../canvas-actions' import type { ControlWithProps } from '../canvas-strategies/canvas-strategy-types' import { controlForStrategyMemoized } from '../canvas-strategies/canvas-strategy-types' diff --git a/editor/src/components/canvas/design-panel-root.tsx b/editor/src/components/canvas/design-panel-root.tsx index 5852f12f0e23..13d381968d01 100644 --- a/editor/src/components/canvas/design-panel-root.tsx +++ b/editor/src/components/canvas/design-panel-root.tsx @@ -35,8 +35,6 @@ import { EditorModes, isCommentMode } from '../editor/editor-modes' import { useAllowedToEditProject } from '../editor/store/collaborative-editing' import { useCanComment } from '../../core/commenting/comment-hooks' import { ElementsOutsideVisibleAreaIndicator } from '../editor/elements-outside-visible-area-indicator' -import { isFeatureEnabled } from '../../utils/feature-switches' -import { RollYourOwnFeaturesPane } from '../navigator/left-pane/roll-your-own-pane' import { AnimationContext } from './ui-jsx-canvas-renderer/animation-context' function isCodeEditorEnabled(): boolean { @@ -163,10 +161,6 @@ export const RightPane = React.memo((props) => { onClickTab(RightMenuTab.Settings) }, [onClickTab]) - const onClickRollYourOwnTab = React.useCallback(() => { - onClickTab(RightMenuTab.RollYourOwn) - }, [onClickTab]) - const canComment = useCanComment() const allowedToEdit = useAllowedToEditProject() @@ -235,14 +229,6 @@ export const RightPane = React.memo((props) => { selected={selectedTab === RightMenuTab.Settings} onClick={onClickSettingsTab} /> - {when( - isFeatureEnabled('Roll Your Own'), - , - )} ((props) => { {when(selectedTab === RightMenuTab.Inspector, )} {when(selectedTab === RightMenuTab.Settings, )} {when(selectedTab === RightMenuTab.Comments, )} - {when(selectedTab === RightMenuTab.RollYourOwn, )} diff --git a/editor/src/components/editor/store/editor-state.ts b/editor/src/components/editor/store/editor-state.ts index 1e83b99dda2f..6f4b09dd4bb9 100644 --- a/editor/src/components/editor/store/editor-state.ts +++ b/editor/src/components/editor/store/editor-state.ts @@ -214,7 +214,6 @@ export enum RightMenuTab { Inspector = 'inspector', Settings = 'settings', Comments = 'comments', - RollYourOwn = 'roll-your-own', } // TODO: this should just contain an NpmDependency and a status diff --git a/editor/src/components/navigator/left-pane/roll-your-own-pane.tsx b/editor/src/components/navigator/left-pane/roll-your-own-pane.tsx deleted file mode 100644 index 08b1df58930f..000000000000 --- a/editor/src/components/navigator/left-pane/roll-your-own-pane.tsx +++ /dev/null @@ -1,275 +0,0 @@ -import React from 'react' -import { Button, FlexColumn, FlexRow, Section } from '../../../uuiui' -import { when } from '../../../utils/react-conditionals' -import { atom, useAtom, useSetAtom } from 'jotai' -import { UIGridRow } from '../../inspector/widgets/ui-grid-row' -import { atomWithStorage } from 'jotai/utils' -import { IS_TEST_ENVIRONMENT } from '../../../common/env-vars' -import { Ellipsis } from './github-pane/github-file-changes-list' -import { deleteParseCache } from '../../../core/shared/parse-cache-utils' -import { useRefEditorState } from '../../../components/editor/store/store-hook' -import type { FeatureName } from '../../../utils/feature-switches' -import { isFeatureEnabled, setFeatureEnabled } from '../../../utils/feature-switches' -import { getParseCacheVersion } from '../../../core/workers/parser-printer/parse-cache-utils.worker' - -const sections = ['Performance'] as const -type Section = (typeof sections)[number] - -type PerformanceFeatures = { - parseCache: boolean - parallelParsing: boolean - cacheArbitraryCode: boolean - verboseLogCache: boolean - logParseTimings: boolean -} - -type RollYourOwnFeaturesTypes = { - Performance: PerformanceFeatures -} - -type RollYourOwnFeatures = { - [K in Section]: RollYourOwnFeaturesTypes[K] -} - -const featureToFeatureFlagMap: Record, FeatureName> = { - parseCache: 'Use Parsing Cache', - verboseLogCache: 'Verbose Log Cache', - cacheArbitraryCode: 'Arbitrary Code Cache', - parallelParsing: 'Parallel Parsing', - logParseTimings: 'Log Parse Timings', -} - -const defaultRollYourOwnFeatures: () => RollYourOwnFeatures = () => ({ - Performance: { - parseCache: getFeatureFlagValue('parseCache'), - parallelParsing: getFeatureFlagValue('parallelParsing'), - cacheArbitraryCode: getFeatureFlagValue('cacheArbitraryCode'), - logParseTimings: getFeatureFlagValue('logParseTimings'), - verboseLogCache: getFeatureFlagValue('verboseLogCache'), - }, -}) - -const ROLL_YOUR_OWN_FEATURES_KEY: string = 'roll-your-own-features' - -let rollYourOwnFeaturesAtom: - | ReturnType> - | ReturnType> - | null = null - -function getRollYourOwnFeaturesAtom() { - if (rollYourOwnFeaturesAtom == null) { - rollYourOwnFeaturesAtom = IS_TEST_ENVIRONMENT - ? atom(defaultRollYourOwnFeatures()) - : atomWithStorage(ROLL_YOUR_OWN_FEATURES_KEY, defaultRollYourOwnFeatures()) - } - return rollYourOwnFeaturesAtom -} - -export function useRollYourOwnFeatures() { - const [features] = useAtom(getRollYourOwnFeaturesAtom()) - const defaultFeatures = defaultRollYourOwnFeatures() - const merged: RollYourOwnFeatures = { - Performance: { - ...defaultFeatures.Performance, - ...syncWithFeatureFlags(features.Performance), - }, - } - return merged -} - -export const RollYourOwnFeaturesPane = React.memo(() => { - const [currentSection, setCurrentSection] = React.useState
(null) - - const onChangeSection = React.useCallback((e: React.ChangeEvent) => { - const maybeSectionValue = e.target.value as Section - if (sections.includes(maybeSectionValue)) { - setCurrentSection(maybeSectionValue) - } else { - setCurrentSection(null) - } - }, []) - - return ( - -
- - Roll Your Own - - - - - - {when(currentSection === 'Performance', )} -
-
- ) -}) -RollYourOwnFeaturesPane.displayName = 'RollYourOwnFeaturesPane' - -function getNewFeatureValueOrNull(currentValue: any, e: React.ChangeEvent) { - switch (typeof currentValue) { - case 'boolean': - return e.target.checked - case 'string': - return e.target.value - case 'number': - return parseFloat(e.target.value) - default: - return null - } -} - -/** PERFORMANCE SECTION */ -const PerformanceSection = React.memo(() => { - const workersRef = useRefEditorState((store) => { - return store.workers - }) - const handleDeleteParseCache = React.useCallback(() => { - deleteParseCache(workersRef.current) - }, [workersRef]) - return ( - - - - Cache Version - {getParseCacheVersion()} - - - - - - ) -}) -PerformanceSection.displayName = 'PerformanceSection' - -/** GENERAL COMPONENTS */ - -const ResetDefaultsButton = React.memo(({ subsection }: { subsection: Section }) => { - const setFeatures = useSetAtom(getRollYourOwnFeaturesAtom()) - const defaultFeatures = defaultRollYourOwnFeatures() - const resetDefaults = React.useCallback(() => { - setFeatures((prevFeatures) => ({ - ...prevFeatures, - [subsection]: defaultFeatures[subsection], - })) - }, [defaultFeatures, setFeatures, subsection]) - return ( - - - - ) -}) -ResetDefaultsButton.displayName = 'ResetDefaultsButton' - -const SimpleFeatureControls = React.memo(({ subsection }: { subsection: Section }) => { - const features = useRollYourOwnFeatures() - const setFeatures = useSetAtom(getRollYourOwnFeaturesAtom()) - const onChange = React.useCallback( - (feat: keyof RollYourOwnFeaturesTypes[Section]) => (e: React.ChangeEvent) => { - const newValue = getNewFeatureValueOrNull(features[subsection][feat], e) - if (newValue != null) { - setFeatures({ - ...features, - [subsection]: { - ...features[subsection], - [feat]: newValue, - }, - }) - if (typeof newValue === 'boolean') { - syncFeatureFlagIfExists(feat, newValue) - } - } - }, - [features, setFeatures, subsection], - ) - const defaultFeatures = defaultRollYourOwnFeatures() - return ( - - {Object.keys(defaultFeatures[subsection]).map((key) => { - const feat = key as keyof RollYourOwnFeaturesTypes[Section] - const featName = Object.keys(featureToFeatureFlagMap).includes( - feat as keyof typeof featureToFeatureFlagMap, - ) - ? featureToFeatureFlagMap[feat as keyof typeof featureToFeatureFlagMap] - : feat - const value = features[subsection][feat] ?? defaultFeatures[subsection][feat] - return ( - - {featName} - {typeof value === 'boolean' ? ( - - ) : typeof value === 'string' ? ( - - ) : typeof value === 'number' ? ( - - ) : null} - - ) - })} - - ) -}) -SimpleFeatureControls.displayName = 'SimpleFeatureControls' - -function getFeatureFlagValue(featureName: keyof typeof featureToFeatureFlagMap): boolean { - const featureFlag = featureToFeatureFlagMap[featureName] - return isFeatureEnabled(featureFlag) -} - -function syncFeatureFlagIfExists( - featureName: keyof typeof featureToFeatureFlagMap, - value: boolean, -) { - const featureFlag = featureToFeatureFlagMap[featureName] - if (featureFlag == null) { - return - } - setFeatureEnabled(featureFlag, value) -} - -function syncWithFeatureFlags(features: Record | undefined) { - if (features == null) { - return {} - } - return Object.fromEntries( - Object.entries(features).map(([key, value]) => { - if (typeof value === 'boolean' && key in featureToFeatureFlagMap) { - return [key, getFeatureFlagValue(key as keyof typeof featureToFeatureFlagMap)] - } - return [key, value] - }), - ) -} diff --git a/editor/src/components/navigator/left-pane/settings-pane.tsx b/editor/src/components/navigator/left-pane/settings-pane.tsx index 90a22afbac08..76741a0993c3 100644 --- a/editor/src/components/navigator/left-pane/settings-pane.tsx +++ b/editor/src/components/navigator/left-pane/settings-pane.tsx @@ -27,8 +27,7 @@ import type { FeatureName } from '../../../utils/feature-switches' import { toggleFeatureEnabled, isFeatureEnabled, - AllFeatureNames, - FeaturesHiddenFromMainSettingsPane, + getFeaturesToDisplay, } from '../../../utils/feature-switches' import json5 from 'json5' import { load } from '../../../components/editor/actions/actions' @@ -60,10 +59,11 @@ const themeOptions = [ const defaultTheme = themeOptions[0] export const FeatureSwitchesSection = React.memo(() => { - const featuresToDisplay = React.useMemo( - () => AllFeatureNames.filter((name) => !FeaturesHiddenFromMainSettingsPane.includes(name)), - [], - ) + const [changeCount, setChangeCount] = React.useState(0) + // this replaces the 'forceRender' in the original implementation + const onFeatureChange = React.useCallback(() => setChangeCount(changeCount + 1), [changeCount]) + // eslint-disable-next-line react-hooks/exhaustive-deps + const featuresToDisplay = React.useMemo(() => getFeaturesToDisplay(), [changeCount]) if (featuresToDisplay.length > 0) { return (
@@ -71,7 +71,11 @@ export const FeatureSwitchesSection = React.memo(() => {

Experimental Toggle Features

{featuresToDisplay.map((name) => ( - + ))}
) @@ -80,15 +84,14 @@ export const FeatureSwitchesSection = React.memo(() => { } }) -const FeatureSwitchRow = React.memo((props: { name: FeatureName }) => { +const FeatureSwitchRow = React.memo((props: { name: FeatureName; onFeatureChange: () => void }) => { const name = props.name + const onFeatureChange = props.onFeatureChange const id = `toggle-${name}` - const [changeCount, setChangeCount] = React.useState(0) - const forceRender = React.useCallback(() => setChangeCount(changeCount + 1), [changeCount]) const onChange = React.useCallback(() => { toggleFeatureEnabled(name) - forceRender() - }, [forceRender, name]) + onFeatureChange() + }, [name, onFeatureChange]) return ( !name.startsWith('Debug')) + } +}