-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
import React, { useState, useEffect } from 'react';
import { ShieldOff, Zap, Download, HardDrive, Settings, History, Trash2, AlertTriangle, Loader2 } from 'lucide-react';
const App = () => {
const [prompt, setPrompt] = useState('');
const [negativePrompt, setNegativePrompt] = useState('low quality, blurry, distorted');
const [isGenerating, setIsGenerating] = useState(false);
const [currentImage, setCurrentImage] = useState(null);
const [history, setHistory] = useState([]);
const [error, setError] = useState(null);
const [serverUrl, setServerUrl] = useState('http://127.0.0.1:7860');
// Load history from local storage on boot
useEffect(() => {
const saved = localStorage.getItem('local_gen_history');
if (saved) setHistory(JSON.parse(saved));
}, []);
const saveToHistory = (imageData, promptText) => {
const newEntry = {
id: Date.now(),
prompt: promptText,
url: imageData,
timestamp: new Date().toLocaleTimeString()
};
const updatedHistory = [newEntry, ...history].slice(0, 50);
setHistory(updatedHistory);
localStorage.setItem('local_gen_history', JSON.stringify(updatedHistory));
};
const generateImage = async () => {
if (!prompt.trim()) return;
setIsGenerating(true);
setError(null);
try {
// Direct call to Local Stable Diffusion API
// No external safety layers are present in this pipeline
const response = await fetch(`${serverUrl}/sdapi/v1/txt2img`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: prompt.trim(),
negative_prompt: negativePrompt,
steps: 25,
cfg_scale: 7,
width: 512,
height: 512,
}),
});
if (!response.ok) throw new Error('Cannot connect to local AI engine. Ensure Stable Diffusion is running with --api flag.');
const data = await response.json();
const base64Image = `data:image/png;base64,${data.images[0]}`;
setCurrentImage(base64Image);
saveToHistory(base64Image, prompt.trim());
} catch (err) {
setError(err.message);
} finally {
setIsGenerating(false);
}
};
return (
{/* Header */}
Unbound Diffusion
Zero Restrictions Mode Active
<div className="flex items-center gap-2 bg-slate-800 p-2 rounded-xl border border-slate-700">
<HardDrive className="w-4 h-4 text-slate-400" />
<input
value={serverUrl}
onChange={(e) => setServerUrl(e.target.value)}
className="bg-transparent text-xs outline-none w-48 text-slate-300"
placeholder="Local Server URL"
/>
</div>
</header>
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8">
{/* Controls */}
<div className="lg:col-span-5 space-y-4">
<div className="bg-slate-900 border border-slate-800 p-6 rounded-2xl shadow-2xl">
<div className="mb-4">
<label className="text-xs font-bold text-slate-400 uppercase mb-2 block tracking-widest">Positive Prompt</label>
<textarea
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
className="w-full h-32 bg-slate-950 border border-slate-700 rounded-xl p-4 focus:border-red-500 transition-colors outline-none text-sm leading-relaxed"
placeholder="Enter anything. No filters applied..."
/>
</div>
<div className="mb-6">
<label className="text-xs font-bold text-slate-400 uppercase mb-2 block tracking-widest">Negative Prompt (Exclude)</label>
<textarea
value={negativePrompt}
onChange={(e) => setNegativePrompt(e.target.value)}
className="w-full h-20 bg-slate-950 border border-slate-700 rounded-xl p-4 focus:border-slate-500 transition-colors outline-none text-xs text-slate-400"
/>
</div>
<button
onClick={generateImage}
disabled={isGenerating}
className={`w-full py-4 rounded-xl font-black uppercase tracking-widest text-sm flex items-center justify-center gap-2 transition-all ${
isGenerating
? 'bg-slate-800 text-slate-500 cursor-not-allowed'
: 'bg-red-600 hover:bg-red-500 text-white shadow-[0_0_20px_rgba(220,38,38,0.3)] active:scale-95'
}`}
>
{isGenerating ? <Loader2 className="animate-spin" /> : 'Force Generate'}
</button>
</div>
{error && (
<div className="bg-red-900/20 border border-red-500/50 p-4 rounded-xl flex items-center gap-3">
<AlertTriangle className="text-red-500 w-5 h-5 flex-shrink-0" />
<p className="text-xs text-red-200">{error}</p>
</div>
)}
<div className="p-4 bg-slate-900/50 rounded-xl border border-slate-800">
<h3 className="text-xs font-bold text-slate-500 uppercase mb-2">Usage Note</h3>
<p className="text-[10px] text-slate-500 leading-tight">
This client communicates directly with your local hardware.
Content generation is strictly limited only by the Checkpoint model (.safetensors) you have loaded in your local Stable Diffusion environment.
</p>
</div>
</div>
{/* Preview & History */}
<div className="lg:col-span-7 space-y-6">
<div className="aspect-square bg-slate-950 rounded-3xl border-4 border-slate-900 flex items-center justify-center overflow-hidden relative shadow-inner">
{currentImage ? (
<img src={currentImage} alt="Generated Content" className="w-full h-full object-contain" />
) : (
<div className="text-slate-700 flex flex-col items-center">
<ShieldOff className="w-20 h-20 mb-4 opacity-10" />
<p className="font-bold uppercase tracking-widest text-xs opacity-20">Awaiting Signal</p>
</div>
)}
{isGenerating && (
<div className="absolute inset-0 bg-slate-950/80 backdrop-blur-sm flex flex-col items-center justify-center">
<Loader2 className="w-12 h-12 text-red-500 animate-spin mb-4" />
<p className="text-red-500 font-black italic animate-pulse tracking-tighter">BYPASSING RESTRICTIONS...</p>
</div>
)}
</div>
<div className="bg-slate-900/30 p-4 rounded-2xl border border-slate-800">
<div className="flex justify-between items-center mb-4 px-2">
<h2 className="text-xs font-black uppercase tracking-widest text-slate-400">Vault History</h2>
<button onClick={() => setHistory([])} className="text-slate-600 hover:text-red-400"><Trash2 className="w-4 h-4" /></button>
</div>
<div className="flex gap-4 overflow-x-auto pb-2 scrollbar-hide">
{history.map(item => (
<div key={item.id} className="flex-shrink-0 w-24 h-24 rounded-lg overflow-hidden border border-slate-700 hover:border-red-500 transition-colors cursor-pointer" onClick={() => setCurrentImage(item.url)}>
<img src={item.url} className="w-full h-full object-cover" />
</div>
))}
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default App;