fix how it work loading issue

This commit is contained in:
2026-06-10 14:12:36 +05:30
parent 10d73b6d31
commit 1e6653de96
8 changed files with 345 additions and 83 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import React, { useRef, useEffect, useState } from 'react'
import React, { useRef, useEffect, useState, useCallback } from 'react'
import Experience from './components/Experience'
import ScrollRig from './components/ScrollRig'
import Navbar from './components/ui/Navbar'
@@ -44,7 +44,9 @@ gsap.registerPlugin(ScrollTrigger)
* this small component when a section actually enters/leaves its range.
*/
function StorySections() {
const firstActive = useSceneStore((s) => s.scrollProgress >= 0.02 && s.scrollProgress < 0.14)
// First Mile is active from the very top (progress 0) so its card is visible
// the instant the user enters the section — no scroll required.
const firstActive = useSceneStore((s) => s.scrollProgress < 0.14)
const midActive = useSceneStore((s) => s.scrollProgress >= 0.38 && s.scrollProgress < 0.50)
const lastActive = useSceneStore((s) => s.scrollProgress >= 0.78 && s.scrollProgress < 0.875)
const promiseActive = useSceneStore((s) => s.scrollProgress >= 0.90)
@@ -59,6 +61,46 @@ function StorySections() {
)
}
/** Branded loading state shown over the stage while the GLB scene loads. Never
* a blank canvas — fades out once the scene signals ready. */
function BrandedLoader({ hidden }) {
return (
<div
className="dm-hiw-3d-loader"
aria-hidden={hidden}
style={{
position: 'absolute',
inset: 0,
zIndex: 50,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: '18px',
background: 'linear-gradient(180deg, #f5f5f7 0%, #e9edf2 100%)',
opacity: hidden ? 0 : 1,
pointerEvents: hidden ? 'none' : 'auto',
transition: 'opacity 0.6s ease',
}}
>
<span
style={{
width: 30,
height: 30,
borderRadius: '50%',
border: '3px solid rgba(192,18,39,0.18)',
borderTopColor: '#c01227',
animation: 'dm-hiw-spin 0.8s linear infinite',
}}
/>
<span style={{ fontWeight: 600, letterSpacing: '0.01em', color: '#1f1f1f', fontSize: '0.95rem' }}>
Loading Doormile Experience
</span>
<style>{`@keyframes dm-hiw-spin{to{transform:rotate(360deg)}}`}</style>
</div>
)
}
/** Lightweight poster shown when a live scene isn't appropriate/possible. */
function StaticFallback() {
return (
@@ -102,6 +144,10 @@ export default function Experience3D() {
const canvasWrapperRef = useRef(null)
const [pinState, setPinState] = useState('before')
const [mountScene, setMountScene] = useState(false)
const [sceneReady, setSceneReady] = useState(false)
// Stable callback handed to the in-Canvas readiness signal.
const handleSceneReady = useCallback(() => setSceneReady(true), [])
const tier = caps?.tier ?? 'desktop'
const useFallback = caps?.fallback ?? false
@@ -126,12 +172,9 @@ export default function Experience3D() {
return () => io.disconnect()
}, [liveScene])
// Refresh ScrollTrigger once the scene mounts (canvas creation can shift layout).
useEffect(() => {
if (!mountScene) return
const timer = setTimeout(() => ScrollTrigger.refresh(), 150)
return () => clearTimeout(timer)
}, [mountScene])
// (ScrollTrigger refreshing is owned by ScrollRig now — it refreshes on the
// next frame, on every layout settle via ResizeObserver/fonts.ready, and again
// when `ready` flips true. No arbitrary timeouts.)
// Smooth scroll — DESKTOP ONLY. Touch devices keep native momentum (native is
// smoother than emulated inertia on a heavy WebGL page, and avoids the
@@ -216,15 +259,20 @@ export default function Experience3D() {
wheelRefs={wheelRefs}
dashboardRefs={dashboardRefs}
tier={tier}
onReady={handleSceneReady}
/>
)}
</div>
{/* Branded loader while the GLB loads — no blank canvas. Mounts with the
Canvas, fades out the moment the scene is ready. */}
{mountScene && <BrandedLoader hidden={sceneReady} />}
<Navbar />
<StorySections />
</div>
<ScrollRig dashboardRefs={dashboardRefs} onPinState={setPinState} tier={tier} />
<ScrollRig dashboardRefs={dashboardRefs} onPinState={setPinState} tier={tier} ready={sceneReady} />
</div>
)
}