Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Replace Dispensed with Forged in the reveal modal, poll builder/progress with indeterminate-until-first-byte UX, and emit interpolated compile progress during long garble builds.
94 lines
3.2 KiB
TypeScript
94 lines
3.2 KiB
TypeScript
import { useEffect } from 'react';
|
|
import type { BuildResponse } from '../../types';
|
|
import { useModalAmbientDuck } from '../../context/AmbientMusicContext';
|
|
import { useSound } from '../../context/SoundContext';
|
|
import DownloadButton from '../DownloadButton';
|
|
import './ForgeDispenseReveal.css';
|
|
|
|
interface Props {
|
|
result: BuildResponse;
|
|
onClose: () => void;
|
|
}
|
|
|
|
function dnaBars(fingerprint?: string): number[] {
|
|
const raw = fingerprint || 'aetherforge';
|
|
const bars: number[] = [];
|
|
for (let i = 0; i < 24; i++) {
|
|
const c = raw.charCodeAt(i % raw.length);
|
|
bars.push(12 + ((c * (i + 3)) % 88));
|
|
}
|
|
return bars;
|
|
}
|
|
|
|
export default function ForgeDispenseReveal({ result, onClose }: Props) {
|
|
useModalAmbientDuck(true);
|
|
const { play } = useSound();
|
|
const score = result.stealth_score ?? 0;
|
|
const bars = dnaBars(result.binary_fingerprint);
|
|
|
|
useEffect(() => {
|
|
play('success');
|
|
}, [play]);
|
|
|
|
return (
|
|
<div className="forge-dispense-backdrop" role="dialog" aria-labelledby="forge-dispense-title">
|
|
<div className="forge-dispense-panel">
|
|
<div className="forge-dispense-sigil" aria-hidden />
|
|
<h2 id="forge-dispense-title" className="forge-dispense-title">
|
|
Forged
|
|
</h2>
|
|
<p className="forge-dispense-sub">
|
|
{result.file_name || 'Your worker'} is ready — each forge carries a unique binary signature.
|
|
</p>
|
|
|
|
<div className="forge-dispense-shield">
|
|
<div
|
|
className="forge-dispense-shield-ring"
|
|
style={{ ['--shield-pct' as string]: `${score}%` }}
|
|
>
|
|
<span className="forge-dispense-shield-value">{score}</span>
|
|
</div>
|
|
<div className="forge-dispense-shield-label">
|
|
<span>Stealth index</span>
|
|
<span className="forge-dispense-shield-hint">Polymorph · Garble · Sigil · Sign</span>
|
|
</div>
|
|
</div>
|
|
|
|
{result.binary_fingerprint && (
|
|
<div className="forge-dispense-dna">
|
|
<span className="forge-dispense-dna-label">Binary DNA</span>
|
|
<code className="forge-dispense-dna-hash">{result.binary_fingerprint}</code>
|
|
<div className="forge-dispense-dna-bars" aria-hidden>
|
|
{bars.map((h, i) => (
|
|
<span key={i} className="forge-dispense-dna-bar" style={{ height: `${h}%` }} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<ul className="forge-dispense-layers">
|
|
<li className={result.obfuscated ? 'on' : ''}>Garble obfuscation</li>
|
|
<li className={result.sigil_scramble ? 'on' : ''}>Sigil scramble</li>
|
|
<li className={result.signed ? 'on' : ''}>Authenticode sign</li>
|
|
<li className="on">Polymorph weave</li>
|
|
</ul>
|
|
|
|
<div className="forge-dispense-actions">
|
|
{result.download_url && result.file_name && (
|
|
<DownloadButton
|
|
apiPath={result.download_url}
|
|
filename={result.file_name}
|
|
className="btn btn-primary"
|
|
>
|
|
↓ Take the forge
|
|
</DownloadButton>
|
|
)}
|
|
<button type="button" className="btn btn-outline" onClick={onClose}>
|
|
Continue forging
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|