Skip to content

Commit 1e71cd6

Browse files
committed
feat: Add Start Button before preloader with sound support
- Add Start Button screen that appears before everything else - Block all page initialization until user clicks Start button - Move sound effect to play when preloader video starts (intro.mp3) - Prevent Firebase, data loading, and UI components from loading until started - Maintain existing video preloader and loading animations after Start click - Add animated background with particles and energy effects for Start screen
1 parent 6923a60 commit 1e71cd6

File tree

3 files changed

+133
-32
lines changed

3 files changed

+133
-32
lines changed

app/home/page.tsx

Lines changed: 128 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,7 @@ export default function HomePageContent() {
10551055
const [showUserProfile, setShowUserProfile] = useState(false);
10561056
const [isVideoPlaying, setIsVideoPlaying] = useState(false);
10571057
const [videoLoaded, setVideoLoaded] = useState(false);
1058+
const [hasStarted, setHasStarted] = useState(false);
10581059

10591060
// Initialize Firebase data on app load
10601061
useEffect(() => {
@@ -1066,14 +1067,15 @@ export default function HomePageContent() {
10661067
if (typeof window !== 'undefined') {
10671068
const hasLoadedBefore = localStorage.getItem('homePageLoaded');
10681069
if (hasLoadedBefore) {
1069-
setIsLoading(false);
1070+
// Don't auto-start anything - wait for user to click start button
1071+
// Keep isLoading as true and hasStarted as false until user clicks
10701072
}
10711073
}
10721074
}, []);
10731075

10741076
// Preloader effect - track actual loading progress
10751077
useEffect(() => {
1076-
if (!isLoading) return; // Skip if already loaded
1078+
if (!isLoading || !hasStarted) return; // Skip if already loaded or not started
10771079

10781080
const loadingSteps = [
10791081
{ progress: 10, message: 'Initializing STELLAR NEXUS...' },
@@ -1107,7 +1109,7 @@ export default function HomePageContent() {
11071109
}, 1000);
11081110

11091111
return () => clearInterval(interval);
1110-
}, [isLoading, isInitialized, demoStats]);
1112+
}, [isLoading, hasStarted, isInitialized, demoStats]);
11111113

11121114
// Fallback timeout to ensure preloader doesn't get stuck
11131115
useEffect(() => {
@@ -1121,10 +1123,19 @@ export default function HomePageContent() {
11211123
}
11221124
}, [isLoading]);
11231125

1124-
// Set video playing state when loading completes
1126+
// Set video playing state when loading completes and play intro sound
11251127
useEffect(() => {
11261128
if (!isLoading) {
11271129
setIsVideoPlaying(true);
1130+
1131+
// Play intro sound when video starts
1132+
try {
1133+
const audio = new Audio('/sounds/intro.mp3');
1134+
audio.volume = 0.6;
1135+
audio.play().catch(() => {}); // Silent fallback if audio fails
1136+
} catch (error) {
1137+
// Silent fallback if audio fails
1138+
}
11281139
}
11291140
}, [isLoading]);
11301141

@@ -1230,6 +1241,13 @@ export default function HomePageContent() {
12301241
setFeedbackDemoData(null);
12311242
};
12321243

1244+
// Handle start button click
1245+
const handleStartClick = () => {
1246+
// Start the experience
1247+
setHasStarted(true);
1248+
setIsLoading(true);
1249+
};
1250+
12331251
return (
12341252
<div className='min-h-screen bg-gradient-to-br from-neutral-900 via-brand-900 to-neutral-900 relative overflow-hidden'>
12351253
{/* Structured Data for SEO */}
@@ -1276,14 +1294,14 @@ export default function HomePageContent() {
12761294
}}
12771295
/>
12781296
{/* Header - Hidden when preloader or video is playing */}
1279-
{!isLoading && !isVideoPlaying && (
1297+
{!isLoading && !isVideoPlaying && hasStarted && (
12801298
<div className='animate-fadeIn'>
12811299
<Header />
12821300
</div>
12831301
)}
12841302

12851303
{/* Authentication Banner - Hidden when preloader or video is playing */}
1286-
{!isLoading && !isVideoPlaying && (
1304+
{!isLoading && !isVideoPlaying && hasStarted && (
12871305
<div className='animate-fadeIn'>
12881306
<AuthBanner onSignUpClick={handleSignUpClick} onSignInClick={handleSignInClick} />
12891307
</div>
@@ -1298,18 +1316,96 @@ export default function HomePageContent() {
12981316
walletSidebarOpen && walletExpanded ? 'mr-96' : walletSidebarOpen ? 'mr-20' : 'mr-0'
12991317
} ${!walletSidebarOpen ? 'pb-32' : 'pb-8'}`}
13001318
>
1301-
{/* Video Preloader Screen */}
1302-
<VideoPreloaderScreen
1303-
isLoading={isLoading}
1304-
title="STELLAR NEXUS EXPERIENCE"
1305-
subtitle="Initializing Stellar Nexus Experience..."
1306-
showText={true}
1307-
minDuration={5000}
1308-
/>
1319+
{/* Start Button Screen - Show before everything else */}
1320+
{!hasStarted && (
1321+
<div className="fixed inset-0 bg-gradient-to-br from-neutral-900 via-brand-900 to-neutral-900 flex items-center justify-center z-[100000]">
1322+
{/* Animated background elements */}
1323+
<div className='absolute inset-0 opacity-20 bg-gradient-to-r from-brand-500/10 via-transparent to-accent-500/10'></div>
1324+
1325+
{/* Floating particles */}
1326+
<div className="absolute inset-0 overflow-hidden pointer-events-none">
1327+
{[...Array(30)].map((_, i) => (
1328+
<div
1329+
key={i}
1330+
className="absolute w-1 h-1 bg-white rounded-full animate-twinkle"
1331+
style={{
1332+
left: `${Math.random() * 100}%`,
1333+
top: `${Math.random() * 100}%`,
1334+
animationDelay: `${Math.random() * 3}s`,
1335+
animationDuration: `${2 + Math.random() * 3}s`,
1336+
}}
1337+
/>
1338+
))}
1339+
</div>
1340+
1341+
<div className="text-center px-4 relative z-10">
1342+
{/* Logo */}
1343+
<div className='flex justify-center mb-8'>
1344+
<Image
1345+
src='/images/logo/logoicon.png'
1346+
alt='STELLAR NEXUS'
1347+
width={200}
1348+
height={200}
1349+
priority
1350+
className="animate-pulse"
1351+
style={{ width: 'auto', height: 'auto', marginBottom: '-50px' }}
1352+
/>
1353+
</div>
1354+
1355+
<p className="text-xl md:text-2xl lg:text-3xl text-white/90 mb-6 drop-shadow-[0_2px_10px_rgba(0,0,0,0.8)]">
1356+
Web3 Early Adopters Program
1357+
</p>
1358+
1359+
{/* Start Button */}
1360+
<div className="relative group">
1361+
{/* Main Button */}
1362+
<button
1363+
onClick={handleStartClick}
1364+
className='relative px-12 py-6 font-bold rounded-2xl transition-all duration-500 transform shadow-2xl border-2 text-2xl hover:scale-110 hover:rotate-1 hover:from-brand-600 hover:via-accent-600 hover:to-brand-700 text-white border-white/30 hover:border-white/60'
1365+
>
1366+
{/* Button Content */}
1367+
<div className='flex items-center justify-center space-x-4'>
1368+
<span>START EXPERIENCE</span>
1369+
</div>
1370+
1371+
{/* Hover Effects */}
1372+
<div className='absolute inset-0 bg-gradient-to-r from-white/0 via-white/10 to-white/0 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-300'></div>
1373+
</button>
1374+
</div>
1375+
1376+
{/* Loading Indicator */}
1377+
<div className="mt-8 animate-fadeInUp">
1378+
<p className="text-white/60 text-sm mt-4">
1379+
Click to begin your journey into the <span className="text-brand-400">Stellar Nexus Experience</span>
1380+
</p>
1381+
</div>
1382+
1383+
{/* Powered by Trustless Work */}
1384+
<div className='text-center mt-4'>
1385+
<p className='text-brand-300/70 text-sm font-medium animate-pulse'>
1386+
Powered by{' '}
1387+
<span className='text-brand-200 font-semibold'>Trustless Work</span>
1388+
</p>
1389+
</div>
13091390

1391+
</div>
1392+
</div>
1393+
)}
1394+
1395+
{/* Video Preloader Screen - Only show after Start button is clicked */}
1396+
{hasStarted && (
1397+
<VideoPreloaderScreen
1398+
isLoading={isLoading}
1399+
title="STELLAR NEXUS EXPERIENCE"
1400+
subtitle="Initializing Stellar Nexus Experience..."
1401+
showText={true}
1402+
minDuration={5000}
1403+
/>
1404+
)}
13101405

1311-
{/* Main Content - Only show when not loading */}
1312-
{!isLoading && (
1406+
1407+
{/* Main Content - Only show when not loading and started */}
1408+
{!isLoading && hasStarted && (
13131409
<>
13141410
{/* Full-Screen Video Overlay with fade-in animation */}
13151411
<video
@@ -1907,7 +2003,7 @@ export default function HomePageContent() {
19072003

19082004

19092005
{/* Footer - Hidden when preloader or video is playing */}
1910-
{!isLoading && !isVideoPlaying && (
2006+
{!isLoading && !isVideoPlaying && hasStarted && (
19112007
<div className='animate-fadeIn'>
19122008
<Footer />
19132009
</div>
@@ -1924,17 +2020,19 @@ export default function HomePageContent() {
19242020
setWalletExpanded(true);
19252021
}
19262022
}}
1927-
showBanner={!isLoading && !isVideoPlaying}
1928-
hideFloatingButton={isLoading || isVideoPlaying}
2023+
showBanner={!isLoading && !isVideoPlaying && hasStarted}
2024+
hideFloatingButton={isLoading || isVideoPlaying || !hasStarted}
19292025
/>
19302026

1931-
{/* NEXUS PRIME Character */}
1932-
<NexusPrime
1933-
currentPage='home'
1934-
currentDemo={activeDemo}
1935-
walletConnected={isConnected}
1936-
autoOpen={isVideoPlaying}
1937-
/>
2027+
{/* NEXUS PRIME Character - Only show after started */}
2028+
{hasStarted && (
2029+
<NexusPrime
2030+
currentPage='home'
2031+
currentDemo={activeDemo}
2032+
walletConnected={isConnected}
2033+
autoOpen={isVideoPlaying}
2034+
/>
2035+
)}
19382036

19392037
{/* Onboarding Overlay */}
19402038
<OnboardingOverlay
@@ -1992,8 +2090,8 @@ export default function HomePageContent() {
19922090
{/* User Profile Modal */}
19932091
<UserProfile isOpen={showUserProfile} onClose={() => setShowUserProfile(false)} />
19942092

1995-
{/* Account Status Indicator */}
1996-
<AccountStatusIndicator />
2093+
{/* Account Status Indicator - Only show after started */}
2094+
{hasStarted && <AccountStatusIndicator />}
19972095

19982096
{/* Demo Feedback Modal */}
19992097
{showFeedbackModal && feedbackDemoData && (
@@ -2014,8 +2112,8 @@ export default function HomePageContent() {
20142112
/>
20152113

20162114

2017-
{/* Toast Container */}
2018-
<ToastContainer />
2115+
{/* Toast Container - Only show after started */}
2116+
{hasStarted && <ToastContainer />}
20192117
</div>
20202118
);
20212119
}

components/layout/NexusPrime.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ export const NexusPrime: React.FC<NexusPrimeProps> = ({
332332

333333
{/* Speech Bubble */}
334334
{isExpanded && (
335-
<div className='absolute bottom-20 left-0 w-80 bg-gradient-to-br from-slate-900/95 to-slate-800/95 backdrop-blur-xl border border-cyan-400/30 rounded-2xl shadow-2xl p-4'>
335+
<div className='absolute bottom-32 left-0 w-80 bg-gradient-to-br from-slate-900/95 to-slate-800/95 backdrop-blur-xl border border-cyan-400/30 rounded-2xl shadow-2xl p-4'>
336336
{/* Arrow */}
337337
<div className='absolute -bottom-2 left-6 w-4 h-4 bg-slate-900/95 border-b border-r border-cyan-400/30 transform rotate-45'></div>
338338

components/ui/quest/QuestAndReferralSection.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Account } from '@/lib/firebase/firebase-types';
55
import { QuestService } from '@/lib/services/quest-service';
66
import { QuestSystem } from './QuestSystem';
77
import { BadgeEmblem } from '@/components/ui/badges/BadgeEmblem';
8+
import { Tooltip } from '../Tooltip';
89

910
interface QuestAndReferralSectionProps {
1011
account: Account | null;
@@ -25,7 +26,9 @@ export const QuestAndReferralSection: React.FC<QuestAndReferralSectionProps> = (
2526
<h3 className="text-xl font-semibold text-white mb-2">Connect Your Wallet</h3>
2627
<p className="text-white/70">Connect your Stellar wallet to access quests and earn rewards</p>
2728
<br/>
28-
<div className="text-8xl mb-6">🎁</div>
29+
<Tooltip content="Complete The Top 5 Badges to Unlock Nexus Quests" position="bottom">
30+
<div className="text-8xl mb-6">🎁</div>
31+
</Tooltip>
2932
</div>
3033
);
3134
}

0 commit comments

Comments
 (0)