fixed unmute for constructor
This commit is contained in:
parent
c3d949702c
commit
9d7e6f6cd2
@ -46,6 +46,10 @@ interface RuntimeControlsProps {
|
|||||||
isMuted?: boolean;
|
isMuted?: boolean;
|
||||||
/** Callback to toggle all presentation sound on/off */
|
/** Callback to toggle all presentation sound on/off */
|
||||||
onSoundToggle?: () => void;
|
onSoundToggle?: () => void;
|
||||||
|
/** Whether to show the offline download button */
|
||||||
|
showOfflineButton?: boolean;
|
||||||
|
/** Whether to show the fullscreen button */
|
||||||
|
showFullscreenButton?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -468,6 +472,8 @@ export default function RuntimeControls({
|
|||||||
showSoundButton = false,
|
showSoundButton = false,
|
||||||
isMuted = true,
|
isMuted = true,
|
||||||
onSoundToggle,
|
onSoundToggle,
|
||||||
|
showOfflineButton = true,
|
||||||
|
showFullscreenButton = true,
|
||||||
}: RuntimeControlsProps) {
|
}: RuntimeControlsProps) {
|
||||||
// Counter-scale to resist pinch-zoom
|
// Counter-scale to resist pinch-zoom
|
||||||
const counterScale = useCounterZoom();
|
const counterScale = useCounterZoom();
|
||||||
@ -520,18 +526,22 @@ export default function RuntimeControls({
|
|||||||
onTouchEnd={stopControlEvent}
|
onTouchEnd={stopControlEvent}
|
||||||
onTouchEndCapture={stopControlEvent}
|
onTouchEndCapture={stopControlEvent}
|
||||||
>
|
>
|
||||||
<OfflineControl
|
{showOfflineButton && (
|
||||||
projectId={projectId}
|
<OfflineControl
|
||||||
projectSlug={projectSlug}
|
projectId={projectId}
|
||||||
projectName={projectName}
|
projectSlug={projectSlug}
|
||||||
pages={pages}
|
projectName={projectName}
|
||||||
/>
|
pages={pages}
|
||||||
<ControlButton
|
/>
|
||||||
icon={isFullscreen ? mdiFullscreenExit : mdiFullscreen}
|
)}
|
||||||
color='info'
|
{showFullscreenButton && (
|
||||||
onClick={toggleFullscreen}
|
<ControlButton
|
||||||
title={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}
|
icon={isFullscreen ? mdiFullscreenExit : mdiFullscreen}
|
||||||
/>
|
color='info'
|
||||||
|
onClick={toggleFullscreen}
|
||||||
|
title={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{showSoundButton && onSoundToggle && (
|
{showSoundButton && onSoundToggle && (
|
||||||
<ControlButton
|
<ControlButton
|
||||||
icon={isMuted ? mdiVolumeOff : mdiVolumeHigh}
|
icon={isMuted ? mdiVolumeOff : mdiVolumeHigh}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import TransitionBlackOverlay from '../components/TransitionBlackOverlay';
|
|||||||
import ConstructorToolbar from '../components/Constructor/ConstructorToolbar';
|
import ConstructorToolbar from '../components/Constructor/ConstructorToolbar';
|
||||||
import TransitionPreviewOverlay from '../components/Constructor/TransitionPreviewOverlay';
|
import TransitionPreviewOverlay from '../components/Constructor/TransitionPreviewOverlay';
|
||||||
import CanvasElementComponent from '../components/Constructor/CanvasElement';
|
import CanvasElementComponent from '../components/Constructor/CanvasElement';
|
||||||
|
import RuntimeControls from '../components/Runtime/RuntimeControls';
|
||||||
import GalleryCarouselOverlay from '../components/UiElements/GalleryCarouselOverlay';
|
import GalleryCarouselOverlay from '../components/UiElements/GalleryCarouselOverlay';
|
||||||
import InfoPanelOverlay from '../components/UiElements/InfoPanelOverlay';
|
import InfoPanelOverlay from '../components/UiElements/InfoPanelOverlay';
|
||||||
import ImageDetailPanel from '../components/UiElements/ImageDetailPanel';
|
import ImageDetailPanel from '../components/UiElements/ImageDetailPanel';
|
||||||
@ -198,7 +199,12 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Canvas scale for responsive UI elements and letterbox mode
|
// Canvas scale for responsive UI elements and letterbox mode
|
||||||
const { cssVars: canvasCssVars, letterboxStyles } = useCanvasScale({
|
const {
|
||||||
|
cssVars: canvasCssVars,
|
||||||
|
letterboxStyles,
|
||||||
|
canvasWidth,
|
||||||
|
canvasHeight,
|
||||||
|
} = useCanvasScale({
|
||||||
designWidth: project?.design_width,
|
designWidth: project?.design_width,
|
||||||
designHeight: project?.design_height,
|
designHeight: project?.design_height,
|
||||||
});
|
});
|
||||||
@ -241,13 +247,6 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
backgroundAudioEndTime,
|
backgroundAudioEndTime,
|
||||||
} = usePageBackground();
|
} = usePageBackground();
|
||||||
|
|
||||||
// Global sound control starts muted for browser autoplay compatibility.
|
|
||||||
const soundControl = useVideoSoundControl({
|
|
||||||
pageHasSound: backgroundVideoMuted === false,
|
|
||||||
hasBackgroundVideo: Boolean(backgroundVideoUrl),
|
|
||||||
hasBackgroundAudio: Boolean(backgroundAudioUrl),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Network-aware transitions: skip video on slow networks, use CSS fade instead
|
// Network-aware transitions: skip video on slow networks, use CSS fade instead
|
||||||
const { shouldUseVideoTransitions, networkInfo } = useNetworkAware();
|
const { shouldUseVideoTransitions, networkInfo } = useNetworkAware();
|
||||||
|
|
||||||
@ -367,6 +366,49 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
[elements],
|
[elements],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const hasElementAudio = useMemo(
|
||||||
|
() =>
|
||||||
|
elements.some((element) => {
|
||||||
|
if (element.hoverAudioUrl || element.clickAudioUrl) return true;
|
||||||
|
if (
|
||||||
|
(element.type === 'audio_player' ||
|
||||||
|
element.type === 'video_player') &&
|
||||||
|
element.mediaUrl &&
|
||||||
|
!element.mediaMuted
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
element.galleryCards?.some(
|
||||||
|
(card: GalleryCarouselMediaItem) =>
|
||||||
|
card.mediaType === 'video' || Boolean(card.videoUrl),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
element.infoPanelSections?.some((section) =>
|
||||||
|
section.images?.some(
|
||||||
|
(item: InfoPanelImage) =>
|
||||||
|
item.itemType === 'video' || Boolean(item.videoUrl),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}),
|
||||||
|
[elements],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Global sound control starts muted for browser autoplay compatibility.
|
||||||
|
const soundControl = useVideoSoundControl({
|
||||||
|
pageHasSound: backgroundVideoMuted === false,
|
||||||
|
hasBackgroundVideo: Boolean(backgroundVideoUrl),
|
||||||
|
hasBackgroundAudio: Boolean(backgroundAudioUrl),
|
||||||
|
hasElementAudio,
|
||||||
|
});
|
||||||
|
|
||||||
// Look up current element for gallery carousel (so it receives updates from element editor)
|
// Look up current element for gallery carousel (so it receives updates from element editor)
|
||||||
const activeGalleryCarouselElement = useMemo(() => {
|
const activeGalleryCarouselElement = useMemo(() => {
|
||||||
if (!activeGalleryCarousel) return null;
|
if (!activeGalleryCarousel) return null;
|
||||||
@ -2184,6 +2226,27 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
</BackdropPortalProvider>
|
</BackdropPortalProvider>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{!isConstructorEditMode &&
|
||||||
|
!activeGalleryCarousel &&
|
||||||
|
!activeInfoPanelGallery &&
|
||||||
|
soundControl.showSoundButton && (
|
||||||
|
<RuntimeControls
|
||||||
|
projectId={projectId || null}
|
||||||
|
projectSlug=''
|
||||||
|
projectName={projectName}
|
||||||
|
pages={pages}
|
||||||
|
isFullscreen={false}
|
||||||
|
toggleFullscreen={() => undefined}
|
||||||
|
canvasWidth={canvasWidth}
|
||||||
|
canvasHeight={canvasHeight}
|
||||||
|
showOfflineButton={false}
|
||||||
|
showFullscreenButton={false}
|
||||||
|
showSoundButton={soundControl.showSoundButton}
|
||||||
|
isMuted={soundControl.isMuted}
|
||||||
|
onSoundToggle={soundControl.toggleSound}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* ElementEditorPanel now uses ConstructorContext for all state */}
|
{/* ElementEditorPanel now uses ConstructorContext for all state */}
|
||||||
{pages.length > 0 && hasEditorSelection && (
|
{pages.length > 0 && hasEditorSelection && (
|
||||||
<ElementEditorPanel
|
<ElementEditorPanel
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user