From 7a72aa7fa78ba8ca36ec6665fa69c49410c59424 Mon Sep 17 00:00:00 2001 From: Dmitri Date: Thu, 25 Jun 2026 11:53:54 +0200 Subject: [PATCH] improved disabling validation --- .../src/components/RuntimePresentation.tsx | 19 ++++++++++++++----- .../UiElements/elements/InfoPanelElement.tsx | 3 ++- frontend/src/lib/elementDefaults.ts | 7 +++++++ frontend/src/pages/constructor.tsx | 7 ++++--- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/RuntimePresentation.tsx b/frontend/src/components/RuntimePresentation.tsx index bb4a271..24d1dda 100644 --- a/frontend/src/components/RuntimePresentation.tsx +++ b/frontend/src/components/RuntimePresentation.tsx @@ -69,7 +69,10 @@ import type { GalleryCarouselMediaItem, InfoPanelImage, } from '../types/constructor'; -import { isInfoPanelElementType } from '../lib/elementDefaults'; +import { + isElementFlagEnabled, + isInfoPanelElementType, +} from '../lib/elementDefaults'; import type { ElementTransitionSettings } from '../types/transition'; import { entityToProjectSettings, @@ -693,10 +696,16 @@ export default function RuntimePresentation({ const handleElementClick = useCallback( (element: CanvasElement) => { - if (isNavigationType(element.type) && element.navDisabled) { + if ( + isNavigationType(element.type) && + isElementFlagEnabled(element.navDisabled) + ) { return; } - if (isInfoPanelElementType(element.type) && element.infoPanelDisabled) { + if ( + isInfoPanelElementType(element.type) && + isElementFlagEnabled(element.infoPanelDisabled) + ) { return; } @@ -1023,9 +1032,9 @@ export default function RuntimePresentation({ element={element} isDisabled={ (isNavigationType(element.type) && - Boolean(element.navDisabled)) || + isElementFlagEnabled(element.navDisabled)) || (isInfoPanelElementType(element.type) && - Boolean(element.infoPanelDisabled)) + isElementFlagEnabled(element.infoPanelDisabled)) } onClick={() => handleElementClick(element)} resolveUrl={resolveUrlWithBlob} diff --git a/frontend/src/components/UiElements/elements/InfoPanelElement.tsx b/frontend/src/components/UiElements/elements/InfoPanelElement.tsx index 05892aa..b44e958 100644 --- a/frontend/src/components/UiElements/elements/InfoPanelElement.tsx +++ b/frontend/src/components/UiElements/elements/InfoPanelElement.tsx @@ -10,6 +10,7 @@ import React from 'react'; import type { CSSProperties } from 'react'; import type { CanvasElement } from '../../../types/constructor'; import { resolveAssetPlaybackUrl } from '../../../lib/assetUrl'; +import { isElementFlagEnabled } from '../../../lib/elementDefaults'; interface InfoPanelElementProps { element: CanvasElement; @@ -27,7 +28,7 @@ const InfoPanelElement: React.FC = ({ onClick, }) => { const resolve = resolveUrl ?? resolveAssetPlaybackUrl; - const isDisabled = element.infoPanelDisabled || false; + const isDisabled = isElementFlagEnabled(element.infoPanelDisabled); const triggerLabel = element.infoPanelTriggerLabel || 'Info'; const fontFamily = element.infoPanelTriggerFontFamily || undefined; diff --git a/frontend/src/lib/elementDefaults.ts b/frontend/src/lib/elementDefaults.ts index 6a06f41..a5ff3f1 100644 --- a/frontend/src/lib/elementDefaults.ts +++ b/frontend/src/lib/elementDefaults.ts @@ -73,6 +73,13 @@ export const createLocalId = (): string => { export const clamp = (value: number, min: number, max: number): number => Math.min(Math.max(value, min), max); +/** + * Strictly parse feature flags stored on element JSON. + */ +export const isElementFlagEnabled = (value: unknown): boolean => + value === true || + (typeof value === 'string' && value.trim().toLowerCase() === 'true'); + /** * Normalize appearDelaySec value */ diff --git a/frontend/src/pages/constructor.tsx b/frontend/src/pages/constructor.tsx index 028c8d4..2791656 100644 --- a/frontend/src/pages/constructor.tsx +++ b/frontend/src/pages/constructor.tsx @@ -63,6 +63,7 @@ import { normalizeAppearDurationSec, ELEMENT_TYPE_LABELS, getNavigationButtonKind, + isElementFlagEnabled, isNavigationElementType, isDescriptionElementType, isMediaElementType, @@ -1475,7 +1476,7 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => { if (transitionPreview || isTransitionBuffering) { return; } - if (element.navDisabled) { + if (isElementFlagEnabled(element.navDisabled)) { return; } @@ -2162,9 +2163,9 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => { isEditMode={isConstructorEditMode} isDisabled={ (isNavigationElementType(element.type) && - Boolean(element.navDisabled)) || + isElementFlagEnabled(element.navDisabled)) || (isInfoPanelElementType(element.type) && - Boolean(element.infoPanelDisabled)) + isElementFlagEnabled(element.infoPanelDisabled)) } onClick={() => onCanvasElementClick(element)} onMouseDown={(event) =>