Wavetype commited on
Commit
3507381
·
verified ·
1 Parent(s): 085cc32

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +86 -228
index.html CHANGED
@@ -3,274 +3,132 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Wavetype Frequency Grid - Flux.1 Klein 9B</title>
7
  <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/css/bootstrap.min.css" rel="stylesheet">
8
  <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.11.1/font/bootstrap-icons.min.css" rel="stylesheet">
9
  <style>
10
- :root {
11
- --border-ai: #ff00ff;
12
- --bg-shade: 0.15;
13
- --accent: #00ff00;
14
- }
15
-
16
- body, html {
17
- margin: 0; padding: 0; width: 100%; height: 100vh;
18
- overflow: hidden; background-color: #000;
19
- font-family: "Courier New", Courier, monospace; color: white;
20
- }
21
-
22
- #sidebar {
23
- position: fixed; left: 0; top: 0; width: 320px; height: 100vh;
24
- background: linear-gradient(180deg, #111 0%, #000 100%);
25
- border-right: 2px solid #333; z-index: 2000;
26
- transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
27
- }
28
-
29
  #sidebar.collapsed { transform: translateX(-320px); }
30
-
31
- #sidebar-toggle {
32
- position: fixed; left: 320px; top: 20px; width: 30px; height: 40px;
33
- background: #111; border: 1px solid #333; border-left: none;
34
- cursor: pointer; z-index: 2001; display: flex; align-items: center;
35
- justify-content: center; color: var(--accent); transition: left 0.3s;
36
- }
37
-
38
  #sidebar.collapsed ~ #sidebar-toggle { left: 0; }
39
-
40
- .auth-status {
41
- padding: 15px; background: #1a1a1a; border-bottom: 1px solid #333;
42
- font-size: 11px; letter-spacing: 1px;
43
- }
44
-
45
- #grid-container {
46
- display: grid; width: 100vw; height: 100vh; gap: 4px; padding: 4px;
47
- padding-left: 324px; transition: padding-left 0.3s;
48
- }
49
-
50
  #sidebar.collapsed ~ #grid-container { padding-left: 4px; }
51
-
52
- .block {
53
- position: relative; background-color: rgba(255, 255, 255, var(--bg-shade));
54
- border: 2px solid #222; display: flex; flex-direction: column;
55
- align-items: center; justify-content: center; cursor: pointer;
56
- overflow: hidden; transition: border-color 0.3s;
57
- }
58
-
59
- .block.active {
60
- position: fixed; top: 0; left: 0; width: 100vw !important;
61
- height: 100vh !important; z-index: 2500; background: #000; padding: 40px;
62
- }
63
-
64
- .close-btn {
65
- display: none; position: absolute; top: 20px; right: 20px;
66
- background: #ff0055; color: white; border: none; padding: 8px 16px;
67
- }
68
  .block.active .close-btn { display: block; }
69
-
70
- .ai-interface { display: none; width: 100%; max-width: 900px; flex-direction: column; gap: 20px; }
71
- .block.active .ai-interface { display: flex; }
72
-
73
- .gen-image-preview {
74
- width: 100%; max-height: 60vh; object-fit: contain;
75
- border: 1px solid var(--border-ai); display: none; background: #050505;
76
- }
77
-
78
- .loading-bar {
79
- height: 2px; width: 0%; background: var(--border-ai);
80
- position: absolute; bottom: 0; left: 0; transition: width 0.3s;
81
- }
82
  </style>
83
  </head>
84
  <body>
85
 
86
  <div id="sidebar">
87
- <div class="auth-status">
88
- <div class="d-flex align-items-center justify-content-between">
89
- <span>HF_AUTH: <span id="tokenLabel" class="text-danger">MISSING</span></span>
90
- <i id="lockIcon" class="bi bi-shield-slash text-danger"></i>
91
- </div>
92
  </div>
93
-
94
  <div class="p-3">
95
- <div class="mb-4">
96
- <label class="form-label small text-muted">GRID DENSITY</label>
97
- <input type="range" class="form-range" id="blockSlider" min="1" max="16" value="4" oninput="updateGrid()">
98
- <div class="d-flex justify-content-between small">
99
- <span id="countVal">4</span> Instances
100
- <span id="saveStatus" class="text-info">Ready</span>
101
- </div>
102
- </div>
103
-
104
- <div class="mb-4">
105
- <label class="form-label small text-muted">SESSION TOKEN</label>
106
- <input type="password" class="form-control form-control-sm bg-dark text-white border-secondary" id="hfToken" placeholder="hf_...">
107
- <div class="form-text" style="font-size: 8px; color: #555;">Token is saved to your browser cache only.</div>
108
  </div>
109
-
110
- <button class="btn btn-sm btn-outline-info w-100 mb-2" onclick="batchGenerate()">BATCH EXECUTE ALL</button>
111
- <button class="btn btn-sm btn-outline-secondary w-100" onclick="saveToCache()">SAVE CONFIG</button>
112
- <button class="btn btn-sm btn-outline-danger w-100 mt-2" onclick="clearAll()">LOGOUT / CLEAR</button>
113
  </div>
114
  </div>
115
 
116
- <button id="sidebar-toggle" onclick="toggleSidebar()"><i class="bi bi-chevron-left"></i></button>
117
-
118
  <div id="grid-container"></div>
119
 
120
  <script>
121
- const container = document.getElementById("grid-container");
122
- const countDisplay = document.getElementById("countVal");
123
- let blocks = [];
124
-
125
- // --- Token Auto-Injection Logic ---
126
- function handleAutoAuth() {
127
- const hfInput = document.getElementById("hfToken");
128
- const urlParams = new URLSearchParams(window.location.search);
129
- const urlToken = urlParams.get('token');
130
-
131
- if (urlToken) {
132
- hfInput.value = urlToken;
133
- saveToCache();
134
- // Clean URL so token isn't in history
135
- window.history.replaceState({}, document.title, window.location.pathname);
136
- updateAuthUI(true);
137
- } else {
138
- const cache = localStorage.getItem("flux_grid_config");
139
- if (cache) {
140
- const data = JSON.parse(cache);
141
- if (data.token) {
142
- hfInput.value = data.token;
143
- updateAuthUI(true);
144
- }
145
- }
146
- }
147
- }
148
-
149
- function updateAuthUI(active) {
150
- const label = document.getElementById("tokenLabel");
151
- const icon = document.getElementById("lockIcon");
152
- if (active) {
153
- label.innerText = "ACTIVE";
154
- label.className = "text-success";
155
- icon.className = "bi bi-shield-lock-fill text-success";
156
- }
157
- }
158
-
159
- function saveToCache() {
160
- const data = {
161
- blocks,
162
- count: document.getElementById("blockSlider").value,
163
- token: document.getElementById("hfToken").value
164
- };
165
- localStorage.setItem("flux_grid_config", JSON.stringify(data));
166
- showStatus("Synced");
167
- }
168
-
169
- function loadFromCache() {
170
- const cache = localStorage.getItem("flux_grid_config");
171
- if (cache) {
172
- const data = JSON.parse(cache);
173
- blocks = data.blocks || [];
174
- document.getElementById("blockSlider").value = data.count || 4;
175
- renderGrid();
176
  } else {
177
- updateGrid();
 
 
178
  }
179
- handleAutoAuth();
 
180
  }
181
 
182
- function updateGrid() {
183
- const count = parseInt(document.getElementById("blockSlider").value);
184
- countDisplay.innerText = count;
185
- while (blocks.length < count) {
186
- blocks.push({ id: Date.now() + Math.random(), prompt: "", lastImg: null });
187
- }
188
- while (blocks.length > count) blocks.pop();
189
- renderGrid();
190
- saveToCache();
191
  }
192
 
193
- function renderGrid() {
194
- const cols = Math.ceil(Math.sqrt(blocks.length)) || 1;
 
 
195
  container.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
196
- container.innerHTML = "";
197
-
198
- blocks.forEach((b, i) => {
199
- const el = document.createElement("div");
200
- el.className = `block`;
201
- el.onclick = () => { if(!el.classList.contains('active')) el.classList.add('active'); };
202
-
203
- el.innerHTML = `
204
- <div class="ai-interface">
205
- <h3 class="text-info">INSTANCE_0${i+1}</h3>
206
- <textarea class="form-control bg-dark text-white border-secondary mb-2" id="prompt-${i}" rows="4" placeholder="Enter prompt...">${b.prompt || ""}</textarea>
207
- <button class="btn btn-info" onclick="generateFlux(${i}, this)">RUN INFERENCE</button>
208
- <div id="loader-${i}" class="text-center mt-2" style="display:none">
209
- <div class="spinner-border spinner-border-sm text-info"></div> PROCESSING...
210
- </div>
211
- <img id="img-${i}" class="gen-image-preview mt-3" src="${b.lastImg || ''}" style="${b.lastImg ? 'display:block' : ''}">
212
  </div>
213
- <div class="text-muted small fw-bold">FLUX_NODE_${i+1}</div>
214
- <div class="loading-bar" id="bar-${i}"></div>
215
  <button class="close-btn" onclick="event.stopPropagation(); this.parentElement.classList.remove('active')">EXIT</button>
216
  `;
217
- container.appendChild(el);
218
  });
219
  }
220
 
221
- async function generateFlux(index, btn) {
222
- if(btn) event.stopPropagation();
223
- const prompt = document.getElementById(`prompt-${index}`).value;
224
- const token = document.getElementById("hfToken").value;
225
- const imgEl = document.getElementById(`img-${index}`);
226
- const loader = document.getElementById(`loader-${index}`);
227
- const bar = document.getElementById(`bar-${index}`);
228
-
229
- if (!prompt || !token) return;
230
-
231
- loader.style.display = "block";
232
- bar.style.width = "50%";
233
- blocks[index].prompt = prompt;
234
 
 
235
  try {
236
- const response = await fetch(
237
- "https://api-inference.huggingface.co/models/Comfy-Org/flux2-klein-9B",
238
- {
239
- headers: { Authorization: `Bearer ${token}` },
240
- method: "POST",
241
- body: JSON.stringify({ inputs: prompt }),
242
- }
243
- );
244
-
245
- const blob = await response.blob();
246
- const objectURL = URL.createObjectURL(blob);
247
- imgEl.src = objectURL;
248
- imgEl.style.display = "block";
249
- blocks[index].lastImg = objectURL;
250
- bar.style.width = "100%";
251
- setTimeout(() => bar.style.width = "0%", 1000);
252
- saveToCache();
253
- } catch (err) {
254
- console.error(err);
255
- } finally {
256
- loader.style.display = "none";
257
- }
258
- }
259
-
260
- async function batchGenerate() {
261
- const promises = blocks.map((_, i) => generateFlux(i, null));
262
- await Promise.all(promises);
263
  }
264
 
265
- function toggleSidebar() { document.getElementById("sidebar").classList.toggle("collapsed"); }
266
- function showStatus(msg) {
267
- const s = document.getElementById("saveStatus");
268
- s.innerText = msg;
269
- setTimeout(() => s.innerText = "Synced", 2000);
 
270
  }
271
- function clearAll() { localStorage.clear(); location.reload(); }
272
 
273
- window.onload = loadFromCache;
274
  </script>
275
  </body>
276
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Wavetype Frequency Grid - Clean</title>
7
  <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/css/bootstrap.min.css" rel="stylesheet">
8
  <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.11.1/font/bootstrap-icons.min.css" rel="stylesheet">
9
  <style>
10
+ :root { --border-ai: #ff00ff; --accent: #00ff00; --bg: #000; }
11
+ body, html { margin: 0; padding: 0; width: 100%; height: 100vh; overflow: hidden; background: var(--bg); color: white; font-family: monospace; }
12
+ #sidebar { position: fixed; left: 0; top: 0; width: 320px; height: 100vh; background: #111; border-right: 1px solid #333; z-index: 2000; transition: transform 0.3s; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  #sidebar.collapsed { transform: translateX(-320px); }
14
+ #sidebar-toggle { position: fixed; left: 320px; top: 20px; z-index: 2001; cursor: pointer; background: #111; color: var(--accent); border: 1px solid #333; border-left: none; padding: 5px; transition: left 0.3s; }
 
 
 
 
 
 
 
15
  #sidebar.collapsed ~ #sidebar-toggle { left: 0; }
16
+ #grid-container { display: grid; width: 100vw; height: 100vh; gap: 4px; padding: 4px 4px 4px 324px; transition: padding 0.3s; }
 
 
 
 
 
 
 
 
 
 
17
  #sidebar.collapsed ~ #grid-container { padding-left: 4px; }
18
+ .block { border: 2px solid #222; background: rgba(255,255,255,0.05); display: flex; align-items: center; justify-content: center; position: relative; cursor: pointer; }
19
+ .block.active { position: fixed; top: 0; left: 0; width: 100vw!important; height: 100vh!important; z-index: 2500; background: #000; padding: 40px; cursor: default; }
20
+ .ai-ui { display: none; width: 100%; max-width: 800px; flex-direction: column; gap: 15px; }
21
+ .block.active .ai-ui { display: flex; }
22
+ .close-btn { display: none; position: absolute; top: 20px; right: 20px; background: #ff0055; color: #fff; border: none; padding: 5px 15px; }
 
 
 
 
 
 
 
 
 
 
 
 
23
  .block.active .close-btn { display: block; }
24
+ .preview-img { width: 100%; max-height: 60vh; object-fit: contain; margin-top: 15px; border: 1px solid var(--border-ai); display: none; }
 
 
 
 
 
 
 
 
 
 
 
 
25
  </style>
26
  </head>
27
  <body>
28
 
29
  <div id="sidebar">
30
+ <div class="p-3 border-bottom border-secondary small">
31
+ HF_AUTH: <span id="authStatus" class="text-danger">MISSING</span>
 
 
 
32
  </div>
 
33
  <div class="p-3">
34
+ <label class="small text-muted">DENSITY</label>
35
+ <input type="range" class="form-range" id="density" min="1" max="16" value="4" oninput="initGrid()">
36
+ <div class="mt-3">
37
+ <label class="small text-muted">TOKEN</label>
38
+ <input type="password" class="form-control form-control-sm bg-dark text-white border-secondary" id="tokenField" placeholder="hf_...">
 
 
 
 
 
 
 
 
39
  </div>
40
+ <button class="btn btn-info btn-sm w-100 mt-4" onclick="save()">SAVE TO CACHE</button>
41
+ <button class="btn btn-outline-danger btn-sm w-100 mt-2" onclick="localStorage.clear(); location.reload();">CLEAR ALL</button>
 
 
42
  </div>
43
  </div>
44
 
45
+ <div id="sidebar-toggle" onclick="document.getElementById('sidebar').classList.toggle('collapsed')"><i class="bi bi-list"></i></div>
 
46
  <div id="grid-container"></div>
47
 
48
  <script>
49
+ let nodes = [];
50
+
51
+ function init() {
52
+ const params = new URLSearchParams(window.location.search);
53
+ const urlKey = params.get('token');
54
+ const hfInp = document.getElementById('tokenField');
55
+
56
+ // Auto-detect token from URL or Cache
57
+ if (urlKey) {
58
+ hfInp.value = urlKey;
59
+ window.history.replaceState({}, '', window.location.pathname); // Clean URL
60
+ save();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  } else {
62
+ const cache = JSON.parse(localStorage.getItem('flux_cfg') || '{}');
63
+ if (cache.token) hfInp.value = cache.token;
64
+ if (cache.count) document.getElementById('density').value = cache.count;
65
  }
66
+ updateStatus();
67
+ initGrid();
68
  }
69
 
70
+ function updateStatus() {
71
+ const hasToken = document.getElementById('tokenField').value.length > 5;
72
+ document.getElementById('authStatus').innerText = hasToken ? "ACTIVE" : "MISSING";
73
+ document.getElementById('authStatus').className = hasToken ? "text-success" : "text-danger";
 
 
 
 
 
74
  }
75
 
76
+ function initGrid() {
77
+ const count = document.getElementById('density').value;
78
+ const container = document.getElementById('grid-container');
79
+ const cols = Math.ceil(Math.sqrt(count));
80
  container.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
81
+ container.innerHTML = '';
82
+ nodes = Array.from({length: count}, (_, i) => ({ id: i, prompt: '' }));
83
+
84
+ nodes.forEach(n => {
85
+ const div = document.createElement('div');
86
+ div.className = 'block';
87
+ div.onclick = () => div.classList.add('active');
88
+ div.innerHTML = `
89
+ <div class="ai-ui">
90
+ <h4 class="text-info">NODE_${n.id + 1}</h4>
91
+ <textarea class="form-control bg-dark text-white" id="p-${n.id}" placeholder="Prompt..."></textarea>
92
+ <button class="btn btn-info mt-2" onclick="gen(${n.id}, this)">GENERATE</button>
93
+ <img id="img-${n.id}" class="preview-img">
 
 
 
94
  </div>
95
+ <div class="small text-muted">FLUX_NODE_${n.id + 1}</div>
 
96
  <button class="close-btn" onclick="event.stopPropagation(); this.parentElement.classList.remove('active')">EXIT</button>
97
  `;
98
+ container.appendChild(div);
99
  });
100
  }
101
 
102
+ async function gen(id, btn) {
103
+ event.stopPropagation();
104
+ const token = document.getElementById('tokenField').value;
105
+ const prompt = document.getElementById(`p-${id}`).value;
106
+ const img = document.getElementById(`img-${id}`);
107
+ if (!token || !prompt) return alert("Missing Token or Prompt");
 
 
 
 
 
 
 
108
 
109
+ btn.disabled = true; btn.innerText = "RUNNING...";
110
  try {
111
+ const res = await fetch("https://api-inference.huggingface.co/models/Comfy-Org/flux2-klein-9B", {
112
+ headers: { Authorization: `Bearer ${token}` },
113
+ method: "POST",
114
+ body: JSON.stringify({ inputs: prompt })
115
+ });
116
+ const blob = await res.blob();
117
+ img.src = URL.createObjectURL(blob);
118
+ img.style.display = 'block';
119
+ } catch (e) { console.error(e); }
120
+ btn.disabled = false; btn.innerText = "GENERATE";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
+ function save() {
124
+ localStorage.setItem('flux_cfg', JSON.stringify({
125
+ token: document.getElementById('tokenField').value,
126
+ count: document.getElementById('density').value
127
+ }));
128
+ updateStatus();
129
  }
 
130
 
131
+ window.onload = init;
132
  </script>
133
  </body>
134
  </html>