Shinhati2023 commited on
Commit
7da53e8
·
verified ·
1 Parent(s): 5a23165

Update client/src/App.jsx

Browse files
Files changed (1) hide show
  1. client/src/App.jsx +39 -27
client/src/App.jsx CHANGED
@@ -3,16 +3,24 @@ import { createClient } from '@supabase/supabase-js';
3
 
4
  // --- CONFIG ---
5
  const SUPABASE_URL = "https://whpciwshxecjvalksicw.supabase.co";
6
- const SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6IndocGNpd3NoeGVjanZhbGtzaWN3Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzAxNDQyNjYsImV4cCI6MjA4NTcyMDI2Nn0.TwWAlQCUstvGykPhaDhPAVpTyg2MV7eltG7JFvjZ-zU"; // <--- PASTE KEY HERE
7
 
8
  const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
9
 
10
- // UPDATED MODEL LIST (Includes Klien 2)
 
11
  const AI_MODELS = [
12
- { id: 'black-forest-labs/FLUX.1-schnell', name: 'FLUX.1 (Fast)' },
13
- { id: 'black-forest-labs/FLUX.1-dev', name: 'FLUX.1 (HD)' },
14
- { id: 'black-forest-labs/FLUX.2-klein-4B', name: 'FLUX.2 Klein (Fast/Edit)' }, // Good for edits
15
- { id: 'black-forest-labs/FLUX.2-klein-9B', name: 'FLUX.2 Klein (Pro/Edit)' },
 
 
 
 
 
 
 
16
  ];
17
 
18
  const ASPECT_RATIOS = [
@@ -26,14 +34,14 @@ const ASPECT_RATIOS = [
26
  function App() {
27
  const [session, setSession] = useState(null);
28
  const [prompt, setPrompt] = useState("");
29
- const [selectedModel, setSelectedModel] = useState(AI_MODELS[2].id); // Default to Klein
30
  const [selectedRatio, setSelectedRatio] = useState(ASPECT_RATIOS[0].id);
31
  const [generating, setGenerating] = useState(false);
32
  const [imageSrc, setImageSrc] = useState(null);
33
 
34
- // NEW: Image Input for Editing
35
- const [inputImage, setInputImage] = useState(null); // Blob for API
36
- const [previewUrl, setPreviewUrl] = useState(null); // URL for UI
37
  const fileInputRef = useRef(null);
38
 
39
  useEffect(() => {
@@ -47,7 +55,6 @@ function App() {
47
  if (error) alert("Login failed: " + error.message);
48
  };
49
 
50
- // Handle File Upload
51
  const handleFileChange = (e) => {
52
  const file = e.target.files[0];
53
  if (file) {
@@ -65,20 +72,24 @@ function App() {
65
  if (!window.puter.auth.isSignedIn()) await window.puter.auth.signIn();
66
 
67
  const ratioConfig = ASPECT_RATIOS.find(r => r.id === selectedRatio);
 
 
68
  const finalPrompt = `${prompt} ${ratioConfig.promptSuffix}`;
69
 
70
  let imgElement;
71
 
72
- // MODE A: IMAGE EDITING (img2img)
73
- if (inputImage) {
74
- // Puter txt2img accepts input_image for editing
 
 
 
 
75
  imgElement = await window.puter.ai.txt2img(finalPrompt, {
76
  model: selectedModel,
77
- input_image: inputImage
78
  });
79
- }
80
- // MODE B: TEXT TO IMAGE
81
- else {
82
  imgElement = await window.puter.ai.txt2img(finalPrompt, {
83
  model: selectedModel
84
  });
@@ -86,7 +97,9 @@ function App() {
86
 
87
  setImageSrc(imgElement.src);
88
  } catch (e) {
89
- alert("Error: " + e.message);
 
 
90
  } finally {
91
  setGenerating(false);
92
  }
@@ -103,7 +116,7 @@ function App() {
103
  <div className="logo-glass"><div className="logo-text">TEK IMAGE GEN</div></div>
104
  <div className="sub-brand">TEKTREY BUILDs</div>
105
  <p style={{color: '#888', fontSize: '0.85rem', marginBottom: '30px', fontFamily: 'monospace'}}>
106
- Generate unlimitedly. Edit Images. 3 every 5mins.
107
  </p>
108
  <button onClick={handleLogin} style={{padding: '18px 50px', fontSize: '1.2rem'}}>LET'S DREAM</button>
109
  </div>
@@ -126,11 +139,11 @@ function App() {
126
  <span style={{fontSize: '0.9rem', fontWeight: 'bold', color: 'white'}}>TEK</span>
127
  </div>
128
  <div style={{display: 'flex', gap: '8px'}}>
129
- <select value={selectedRatio} onChange={(e) => setSelectedRatio(e.target.value)} style={{padding: '8px', fontSize: '0.75rem', width: 'auto', maxWidth: '80px'}}>
130
- {ASPECT_RATIOS.map(r => <option key={r.id} value={r.id} style={{color:'black'}}>{r.name}</option>)}
131
  </select>
132
- <select value={selectedModel} onChange={(e) => setSelectedModel(e.target.value)} style={{padding: '8px', fontSize: '0.75rem', width: 'auto', maxWidth: '100px'}}>
133
- {AI_MODELS.map(m => <option key={m.id} value={m.id} style={{color:'black'}}>{m.name}</option>)}
134
  </select>
135
  </div>
136
  </div>
@@ -154,7 +167,7 @@ function App() {
154
  )}
155
  </div>
156
 
157
- {/* INPUT DOCK & UPLOAD */}
158
  <div style={{
159
  position: 'fixed', bottom: 0, left: 0, right: 0,
160
  padding: '10px 20px 30px 20px',
@@ -166,7 +179,7 @@ function App() {
166
  <div style={{position: 'absolute', bottom: '90px', left: '20px', zIndex: 30}}>
167
  <div className="holo-box" style={{padding: '5px', marginBottom: 0, display: 'inline-block'}}>
168
  <img src={previewUrl} style={{height: '60px', borderRadius: '4px'}} />
169
- <button onClick={() => {setPreviewUrl(null); setInputImage(null);}} style={{position: 'absolute', top: -5, right: -5, padding: '2px 6px', fontSize: '10px', background: 'red'}}>X</button>
170
  </div>
171
  </div>
172
  )}
@@ -191,7 +204,6 @@ function App() {
191
  }}
192
  />
193
 
194
- {/* RUN BUTTON */}
195
  <button
196
  onClick={handleGenerate} disabled={generating}
197
  style={{
 
3
 
4
  // --- CONFIG ---
5
  const SUPABASE_URL = "https://whpciwshxecjvalksicw.supabase.co";
6
+ const SUPABASE_ANON_KEY = "PASTE_YOUR_ANON_KEY_HERE"; // <--- PASTE KEY HERE
7
 
8
  const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
9
 
10
+ // --- THE GOD MODE MODEL LIST ---
11
+ //
12
  const AI_MODELS = [
13
+ // FLUX FAMILY
14
+ { id: 'black-forest-labs/FLUX.1-schnell', name: 'FLUX.1 Schnell (Fastest)' },
15
+ { id: 'black-forest-labs/FLUX.1-dev', name: 'FLUX.1 Dev (High Quality)' },
16
+ { id: 'black-forest-labs/FLUX.1-pro', name: 'FLUX.1 Pro (Ultra)' },
17
+
18
+ // THE "KONTEXT" YOU REQUESTED
19
+ { id: 'black-forest-labs/FLUX.1-Kontext', name: 'FLUX.1 Kontext (Special)' },
20
+
21
+ // OPENAI & OTHERS
22
+ { id: 'openai/dall-e-3', name: 'DALL-E 3 (GPT-4o Engine)' },
23
+ { id: 'grok-2-image', name: 'Grok 2 (xAI)' },
24
  ];
25
 
26
  const ASPECT_RATIOS = [
 
34
  function App() {
35
  const [session, setSession] = useState(null);
36
  const [prompt, setPrompt] = useState("");
37
+ const [selectedModel, setSelectedModel] = useState(AI_MODELS[0].id);
38
  const [selectedRatio, setSelectedRatio] = useState(ASPECT_RATIOS[0].id);
39
  const [generating, setGenerating] = useState(false);
40
  const [imageSrc, setImageSrc] = useState(null);
41
 
42
+ // Image Input State
43
+ const [inputImage, setInputImage] = useState(null);
44
+ const [previewUrl, setPreviewUrl] = useState(null);
45
  const fileInputRef = useRef(null);
46
 
47
  useEffect(() => {
 
55
  if (error) alert("Login failed: " + error.message);
56
  };
57
 
 
58
  const handleFileChange = (e) => {
59
  const file = e.target.files[0];
60
  if (file) {
 
72
  if (!window.puter.auth.isSignedIn()) await window.puter.auth.signIn();
73
 
74
  const ratioConfig = ASPECT_RATIOS.find(r => r.id === selectedRatio);
75
+ // DALL-E 3 handles ratios differently (params), but Flux uses prompt suffixes.
76
+ // We append mostly for Flux, Puter handles DALL-E 3 best-effort mapping.
77
  const finalPrompt = `${prompt} ${ratioConfig.promptSuffix}`;
78
 
79
  let imgElement;
80
 
81
+ // MODE CHECK: DALL-E 3 does NOT support img2img input in this API version
82
+ if (inputImage && selectedModel.includes('dall-e-3')) {
83
+ alert("Note: DALL-E 3 ignores input images. Switching to Text generation.");
84
+ imgElement = await window.puter.ai.txt2img(finalPrompt, { model: selectedModel });
85
+ }
86
+ else if (inputImage) {
87
+ // Try to use input image for supported models
88
  imgElement = await window.puter.ai.txt2img(finalPrompt, {
89
  model: selectedModel,
90
+ image: inputImage
91
  });
92
+ } else {
 
 
93
  imgElement = await window.puter.ai.txt2img(finalPrompt, {
94
  model: selectedModel
95
  });
 
97
 
98
  setImageSrc(imgElement.src);
99
  } catch (e) {
100
+ console.error(e);
101
+ // Puter errors can be vague, usually it's "Model Busy" or "Invalid Param"
102
+ alert("Generation Error: " + (e.message || "Model failed. Try a different one."));
103
  } finally {
104
  setGenerating(false);
105
  }
 
116
  <div className="logo-glass"><div className="logo-text">TEK IMAGE GEN</div></div>
117
  <div className="sub-brand">TEKTREY BUILDs</div>
118
  <p style={{color: '#888', fontSize: '0.85rem', marginBottom: '30px', fontFamily: 'monospace'}}>
119
+ Unlimited Generation. DALL-E 3 + FLUX + KONTEXT.
120
  </p>
121
  <button onClick={handleLogin} style={{padding: '18px 50px', fontSize: '1.2rem'}}>LET'S DREAM</button>
122
  </div>
 
139
  <span style={{fontSize: '0.9rem', fontWeight: 'bold', color: 'white'}}>TEK</span>
140
  </div>
141
  <div style={{display: 'flex', gap: '8px'}}>
142
+ <select value={selectedRatio} onChange={(e) => setSelectedRatio(e.target.value)} style={{padding: '8px', fontSize: '0.75rem', width: 'auto', maxWidth: '80px', color:'black'}}>
143
+ {ASPECT_RATIOS.map(r => <option key={r.id} value={r.id}>{r.name}</option>)}
144
  </select>
145
+ <select value={selectedModel} onChange={(e) => setSelectedModel(e.target.value)} style={{padding: '8px', fontSize: '0.75rem', width: 'auto', maxWidth: '120px', color:'black'}}>
146
+ {AI_MODELS.map(m => <option key={m.id} value={m.id}>{m.name}</option>)}
147
  </select>
148
  </div>
149
  </div>
 
167
  )}
168
  </div>
169
 
170
+ {/* INPUT DOCK */}
171
  <div style={{
172
  position: 'fixed', bottom: 0, left: 0, right: 0,
173
  padding: '10px 20px 30px 20px',
 
179
  <div style={{position: 'absolute', bottom: '90px', left: '20px', zIndex: 30}}>
180
  <div className="holo-box" style={{padding: '5px', marginBottom: 0, display: 'inline-block'}}>
181
  <img src={previewUrl} style={{height: '60px', borderRadius: '4px'}} />
182
+ <button onClick={() => {setPreviewUrl(null); setInputImage(null);}} style={{position: 'absolute', top: -5, right: -5, padding: '2px 6px', fontSize: '10px', background: 'red', border:'none', color:'white', borderRadius:'4px', cursor:'pointer'}}>X</button>
183
  </div>
184
  </div>
185
  )}
 
204
  }}
205
  />
206
 
 
207
  <button
208
  onClick={handleGenerate} disabled={generating}
209
  style={{