Files
Shadowbroker/frontend/src/components/HlsVideo.tsx
T
anoracleofra-code 668ce16dc7 v0.9.6: InfoNet hashchain, Wormhole gate encryption, mesh reputation, 16 community contributors
Gate messages now propagate via the Infonet hashchain as encrypted blobs — every node syncs them
through normal chain sync while only Gate members with MLS keys can decrypt. Added mesh reputation
system, peer push workers, voluntary Wormhole opt-in for node participation, fork recovery,
killwormhole scripts, obfuscated terminology, and hardened the self-updater to protect encryption
keys and chain state during updates.

New features: Shodan search, train tracking, Sentinel Hub imagery, 8 new intelligence layers,
CCTV expansion to 11,000+ cameras across 6 countries, Mesh Terminal CLI, prediction markets,
desktop-shell scaffold, and comprehensive mesh test suite (215 frontend + backend tests passing).

Community contributors: @wa1id, @AlborzNazari, @adust09, @Xpirix, @imqdcr, @csysp, @suranyami,
@chr0n1x, @johan-martensson, @singularfailure, @smithbh, @OrfeoTerkuci, @deuza, @tm-const,
@Elhard1, @ttulttul
2026-03-26 05:58:04 -06:00

67 lines
1.7 KiB
TypeScript

'use client';
import { useEffect, useRef, forwardRef, useImperativeHandle } from 'react';
export interface HlsVideoHandle {
play(): void;
pause(): void;
get paused(): boolean;
}
const HlsVideo = forwardRef<HlsVideoHandle, { url: string; className?: string; onError?: () => void }>(
({ url, className, onError }, ref) => {
const videoRef = useRef<HTMLVideoElement>(null);
useImperativeHandle(ref, () => ({
play: () => videoRef.current?.play(),
pause: () => videoRef.current?.pause(),
get paused() {
return videoRef.current?.paused ?? true;
},
}));
useEffect(() => {
const video = videoRef.current;
if (!video || !url) return;
let hlsInstance: { destroy(): void } | null = null;
let cancelled = false;
(async () => {
const { default: Hls } = await import('hls.js');
if (cancelled) return;
if (Hls.isSupported()) {
const hls = new Hls({ enableWorker: false, lowLatencyMode: true });
hls.on(Hls.Events.ERROR, (_e: unknown, data: { fatal?: boolean }) => {
if (data.fatal) onError?.();
});
hls.loadSource(url);
hls.attachMedia(video);
hlsInstance = hls;
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = url;
}
})();
return () => {
cancelled = true;
hlsInstance?.destroy();
};
}, [url, onError]);
return (
<video
ref={videoRef}
autoPlay
muted
playsInline
onError={() => onError?.()}
className={className}
/>
);
},
);
HlsVideo.displayName = 'HlsVideo';
export default HlsVideo;