link menus to windows
This commit is contained in:
parent
0f8a089188
commit
73f0910d91
2 changed files with 65 additions and 79 deletions
126
src/App.tsx
126
src/App.tsx
|
|
@ -1,91 +1,69 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
// import Day1Desktop from './Day1Desktop';
|
import CybersecMenu from './cases/CybersecMenu';
|
||||||
import MainApp from './MainApp';
|
|
||||||
import ChatterboxTTS from './components/deepfake/ChatterboxTTS';
|
|
||||||
import Case1Desktop from './cases/Case1Desktop';
|
import Case1Desktop from './cases/Case1Desktop';
|
||||||
import Case2Desktop from './cases/Case2Desktop';
|
import Case2Desktop from './cases/Case2Desktop';
|
||||||
import Case3Desktop from './cases/Case3Desktop';
|
import Case3Desktop from './cases/Case3Desktop';
|
||||||
import Case4Desktop from './cases/Case4Desktop';
|
import Case4Desktop from './cases/Case4Desktop';
|
||||||
|
import ChatterboxTTS from './components/deepfake/ChatterboxTTS';
|
||||||
import MyQuize from './components/MyQuize';
|
import MyQuize from './components/MyQuize';
|
||||||
import CyberSecurityArticle from './components/CyberSecurityArticle';
|
import CyberSecurityArticle from './components/CyberSecurityArticle';
|
||||||
|
|
||||||
export type WallpaperType = 'xp' | 'win7' | 'win10';
|
export type WallpaperType = 'xp' | 'win7' | 'win10';
|
||||||
|
|
||||||
|
type OverlayType = 'case1' | 'case2' | 'case3' | 'case4' | 'deepfake' | 'quiz' | 'wiki' | null;
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
// const [day1Complete, setDay1Complete] = useState(false);
|
const [overlay, setOverlay] = useState<OverlayType>(null);
|
||||||
// if (!day1Complete) {
|
|
||||||
// return <Day1Desktop onComplete={() => setDay1Complete(true)} />;
|
|
||||||
// }
|
|
||||||
// return <ChatterboxTTS/>
|
|
||||||
|
|
||||||
const [showCase1, setShowCase1] = useState(false);
|
const close = () => setOverlay(null);
|
||||||
const [showCase2, setShowCase2] = useState(false);
|
|
||||||
const [showCase3, setShowCase3] = useState(false);
|
|
||||||
const [showCase4, setShowCase4] = useState(false);
|
|
||||||
const [showWiki, setShowWiki] = useState(false);
|
|
||||||
const [showQuiz, setShowQuiz] = useState(false);
|
|
||||||
const [showDeepfake, setDeepfake] = useState(false);
|
|
||||||
|
|
||||||
return (<div>
|
const handleSelectLevel = (level: number | string) => {
|
||||||
<h1>Хайо</h1>
|
const map: Record<string | number, OverlayType> = {
|
||||||
<button onClick={()=> { setShowQuiz(true) }}>Квиз блок</button>
|
1: 'case1',
|
||||||
<button onClick={()=> { setDeepfake(true) }}>Deepfake блок</button>
|
2: 'case2',
|
||||||
<button onClick={()=> { setShowWiki(true) }}>Wiki блок</button>
|
3: 'case3',
|
||||||
<button onClick={()=> { setShowCase1(true) }}>Первый блок</button>
|
4: 'case4',
|
||||||
<button onClick={()=> { setShowCase2(true) }}>Второй блок</button>
|
'deepfake': 'deepfake',
|
||||||
<button onClick={()=> { setShowCase3(true) }}>Третий блок</button>
|
};
|
||||||
<button onClick={()=> { setShowCase4(true) }}>Четвертый блок</button>
|
setTimeout(() => setOverlay(map[level] ?? null), 1200);
|
||||||
{showWiki && (
|
};
|
||||||
<div>
|
|
||||||
<CyberSecurityArticle/>;
|
return (
|
||||||
</div>
|
<div style={{ width: '100vw', height: '100vh', overflow: 'hidden', position: 'relative' }}>
|
||||||
)}
|
<CybersecMenu
|
||||||
{showCase1 && (
|
onSelectLevel={handleSelectLevel}
|
||||||
<div>
|
onOpenWiki={() => setTimeout(() => setOverlay('wiki'), 1200)}
|
||||||
<Case1Desktop onComplete={() => setShowCase1(false)} />;
|
onOpenQuiz={() => setTimeout(() => setOverlay('quiz'), 1200)}
|
||||||
</div>
|
/>
|
||||||
)}
|
|
||||||
{showCase2 && (
|
{overlay && (
|
||||||
<div>
|
<div style={{
|
||||||
<Case2Desktop onComplete={() => setShowCase2(false)} />;
|
position: 'fixed', inset: 0, zIndex: 50000,
|
||||||
</div>
|
background: 'rgba(0,0,0,0.85)',
|
||||||
)}
|
overflowY: 'auto',
|
||||||
{showCase3 && (
|
}}>
|
||||||
<div>
|
<div style={{ position: 'relative', minHeight: '100%' }}>
|
||||||
<Case3Desktop onComplete={() => setShowCase3(false)} />;
|
<button onClick={close} style={{
|
||||||
</div>
|
position: 'sticky', top: 16, float: 'right', marginRight: 24, zIndex: 1,
|
||||||
)}
|
background: 'rgba(0,0,0,0.8)', border: '1px solid #00FF41',
|
||||||
{showCase4 && (
|
color: '#00FF41', fontFamily: 'Orbitron, monospace',
|
||||||
<div>
|
fontSize: 12, letterSpacing: 2, padding: '6px 14px',
|
||||||
<Case4Desktop onComplete={() => setShowCase4(false)} />;
|
cursor: 'pointer',
|
||||||
</div>
|
}}>✕ ЗАКРЫТЬ</button>
|
||||||
)}
|
<div style={{ clear: 'both' }} />
|
||||||
|
|
||||||
{showQuiz && (
|
{overlay === 'case1' && <Case1Desktop onComplete={close} />}
|
||||||
<div>
|
{overlay === 'case2' && <Case2Desktop onComplete={close} />}
|
||||||
<MyQuize/>;
|
{overlay === 'case3' && <Case3Desktop onComplete={close} />}
|
||||||
</div>
|
{overlay === 'case4' && <Case4Desktop onComplete={close} />}
|
||||||
)}
|
{overlay === 'deepfake' && <ChatterboxTTS />}
|
||||||
{showDeepfake && (
|
{overlay === 'quiz' && <MyQuize />}
|
||||||
<div>
|
{overlay === 'wiki' && <CyberSecurityArticle />}
|
||||||
<ChatterboxTTS/>;
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>);
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
const App: React.FC = () => {
|
|
||||||
// const [day1Complete, setDay1Complete] = useState(false);
|
|
||||||
|
|
||||||
// if (!day1Complete) {
|
|
||||||
// return <Day1Desktop onComplete={() => setDay1Complete(true)} />;
|
|
||||||
// }
|
|
||||||
// return <ChatterboxTTS/>
|
|
||||||
// return <MainApp />;
|
|
||||||
return <MainApp />;
|
|
||||||
};*/
|
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,13 @@ interface Notification {
|
||||||
removing: boolean;
|
removing: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CybersecMenu: React.FC = () => {
|
interface CybersecMenuProps {
|
||||||
|
onSelectLevel?: (level: number | string) => void;
|
||||||
|
onOpenWiki?: () => void;
|
||||||
|
onOpenQuiz?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CybersecMenu: React.FC<CybersecMenuProps> = ({ onSelectLevel, onOpenWiki, onOpenQuiz }) => {
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
const animFrameRef = useRef<number>(0);
|
const animFrameRef = useRef<number>(0);
|
||||||
const smokeOffsetRef = useRef(0);
|
const smokeOffsetRef = useRef(0);
|
||||||
|
|
@ -36,16 +42,18 @@ const CybersecMenu: React.FC = () => {
|
||||||
'deepfake': 'Voice deepfake – AI-generated speech',
|
'deepfake': 'Voice deepfake – AI-generated speech',
|
||||||
};
|
};
|
||||||
showNotification(`>> LEVEL ${level} SELECTED`, levelNames[level]);
|
showNotification(`>> LEVEL ${level} SELECTED`, levelNames[level]);
|
||||||
}, [showNotification]);
|
onSelectLevel?.(level);
|
||||||
|
}, [showNotification, onSelectLevel]);
|
||||||
|
|
||||||
const openWiki = useCallback(() => {
|
const openWiki = useCallback(() => {
|
||||||
showNotification('>> ACCESSING WIKI', 'Security knowledge base loading...');
|
showNotification('>> ACCESSING WIKI', 'Security knowledge base loading...');
|
||||||
}, [showNotification]);
|
onOpenWiki?.();
|
||||||
|
}, [showNotification, onOpenWiki]);
|
||||||
|
|
||||||
const openQuiz = useCallback(() => {
|
const openQuiz = useCallback(() => {
|
||||||
showNotification('>> INITIATING QUIZ', 'Test your skills module loading...');
|
showNotification('>> INITIATING QUIZ', 'Test your skills module loading...');
|
||||||
|
onOpenQuiz?.();
|
||||||
}, [showNotification]);
|
}, [showNotification, onOpenQuiz]);
|
||||||
|
|
||||||
// Keyboard navigation
|
// Keyboard navigation
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue