2ch commited on
Commit
bf56852
·
verified ·
1 Parent(s): 210789e

Update Grok Imagine Pro UI v2.5-2.5.user.js

Browse files
Files changed (1) hide show
  1. Grok Imagine Pro UI v2.5-2.5.user.js +107 -24
Grok Imagine Pro UI v2.5-2.5.user.js CHANGED
@@ -69,6 +69,32 @@
69
  #modal-next { right: 20px; }
70
  #modal-download { position:absolute;top:40px; left:auto;width:auto; padding:0 25px; background:var(--color-green-500); color:#000; text-decoration:none; line-height:44px; font-weight:bold; border-radius:6px; box-shadow:black 0px 0px 10px 2px }
71
  .status { color: #888; font-size: 13px; font-family: monospace; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  `;
73
  document.head.appendChild(style);
74
 
@@ -117,6 +143,7 @@
117
  </select>
118
  <button id="gen-btn">GENERATE</button>
119
  <button class="btn-danger" id="clear-gallery">Clear Gallery</button>
 
120
  <span id="global-status" class="status"></span>
121
  </div>
122
  </div>
@@ -152,18 +179,72 @@
152
  }
153
  });
154
 
 
155
  const fileInput = document.getElementById('file-input');
156
  const uploadBtn = document.getElementById('upload-btn');
157
- const clearFilesBtn = document.getElementById('clear-files');
158
  const ratioSelect = document.getElementById('ratio-select');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
- uploadBtn.onclick = () => fileInput.click();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
- fileInput.onchange = async (e) => {
163
- const files = Array.from(e.target.files).slice(0, 10);
164
- selectedImages = [];
 
165
 
166
- for (const file of files) {
167
  const base64 = await new Promise(resolve => {
168
  const reader = new FileReader();
169
  reader.onload = () => resolve(reader.result);
@@ -171,26 +252,28 @@
171
  });
172
  selectedImages.push({ url: base64 });
173
  }
 
 
174
 
175
- if (selectedImages.length > 0) {
176
- uploadBtn.innerText = `📎 Edit (${selectedImages.length}/10)`;
177
- uploadBtn.style.color = "#0f0";
178
- clearFilesBtn.style.display = "inline-block";
179
- ratioSelect.disabled = true;
180
- ratioSelect.value = "auto";
181
- document.getElementById('gen-btn').innerText = "EDIT IMAGES";
182
- }
183
- };
184
 
185
- clearFilesBtn.onclick = () => {
186
- selectedImages = [];
187
- fileInput.value = "";
188
- uploadBtn.innerText = "📎 Edit (0/10)";
189
- uploadBtn.style.color = "#fff";
190
- clearFilesBtn.style.display = "none";
191
- ratioSelect.disabled = false;
192
- document.getElementById('gen-btn').innerText = "GENERATE";
193
- };
 
 
 
 
 
 
194
 
195
  renderHistory();
196
  }
 
69
  #modal-next { right: 20px; }
70
  #modal-download { position:absolute;top:40px; left:auto;width:auto; padding:0 25px; background:var(--color-green-500); color:#000; text-decoration:none; line-height:44px; font-weight:bold; border-radius:6px; box-shadow:black 0px 0px 10px 2px }
71
  .status { color: #888; font-size: 13px; font-family: monospace; }
72
+
73
+ /* Превью референсов */
74
+ #reference-previews {
75
+ display: flex; gap: 10px; margin-top: 10px; flex-wrap: wrap;
76
+ min-height: 20px; padding: 10px; border: 2px dashed transparent;
77
+ border-radius: 8px; transition: 0.2s;
78
+ }
79
+ #reference-previews.drag-over { border-color: #0f0; background: rgba(0,255,0,0.05); }
80
+
81
+ .ref-item {
82
+ width: 80px; height: 80px; position: relative; cursor: grab;
83
+ border: 2px solid #333; border-radius: 6px; overflow: hidden;
84
+ background: #000; transition: transform 0.2s;
85
+ }
86
+ .ref-item:active { cursor: grabbing; }
87
+ .ref-item img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
88
+ .ref-item .remove-ref {
89
+ position: absolute; top: 2px; right: 2px; background: rgba(0,0,0,0.7);
90
+ color: #ff4444; border: none; border-radius: 4px; padding: 0 4px;
91
+ font-size: 12px; cursor: pointer; z-index: 2;
92
+ }
93
+ .ref-item .ref-index {
94
+ position: absolute; bottom: 2px; left: 2px; background: rgba(0,0,0,0.7);
95
+ color: #fff; font-size: 10px; padding: 0 4px; border-radius: 4px;
96
+ }
97
+ .ref-item.dragging { opacity: 0.5; transform: scale(0.9); }
98
  `;
99
  document.head.appendChild(style);
100
 
 
143
  </select>
144
  <button id="gen-btn">GENERATE</button>
145
  <button class="btn-danger" id="clear-gallery">Clear Gallery</button>
146
+ <div id="reference-previews"></div>
147
  <span id="global-status" class="status"></span>
148
  </div>
149
  </div>
 
179
  }
180
  });
181
 
182
+ const refContainer = document.getElementById('reference-previews');
183
  const fileInput = document.getElementById('file-input');
184
  const uploadBtn = document.getElementById('upload-btn');
 
185
  const ratioSelect = document.getElementById('ratio-select');
186
+ const genBtn = document.getElementById('gen-btn');
187
+
188
+ // Функция обновления UI референсов
189
+ function renderRefPreviews() {
190
+ refContainer.innerHTML = '';
191
+ selectedImages.forEach((imgObj, index) => {
192
+ const item = document.createElement('div');
193
+ item.className = 'ref-item';
194
+ item.draggable = true;
195
+ item.dataset.index = index;
196
+ item.innerHTML = `
197
+ <img src="${imgObj.url}">
198
+ <button class="remove-ref">✕</button>
199
+ <span class="ref-index">${index + 1}</span>
200
+ `;
201
 
202
+ // Удаление одного референса
203
+ item.querySelector('.remove-ref').onclick = (e) => {
204
+ e.stopPropagation();
205
+ selectedImages.splice(index, 1);
206
+ updateEditState();
207
+ };
208
+
209
+ // Логика сортировки (Drag & Drop элементов)
210
+ item.ondragstart = (e) => {
211
+ e.dataTransfer.setData('text/plain', index);
212
+ item.classList.add('dragging');
213
+ };
214
+ item.ondragend = () => item.classList.remove('dragging');
215
+
216
+ item.ondragover = (e) => e.preventDefault();
217
+ item.ondrop = (e) => {
218
+ e.preventDefault();
219
+ const fromIdx = parseInt(e.dataTransfer.getData('text/plain'));
220
+ const toIdx = index;
221
+ if (fromIdx === toIdx) return;
222
+
223
+ const movedItem = selectedImages.splice(fromIdx, 1)[0];
224
+ selectedImages.splice(toIdx, 0, movedItem);
225
+ updateEditState();
226
+ };
227
+
228
+ refContainer.appendChild(item);
229
+ });
230
+ }
231
+
232
+ function updateEditState() {
233
+ const count = selectedImages.length;
234
+ uploadBtn.innerText = `📎 Edit (${count}/10)`;
235
+ uploadBtn.style.color = count > 0 ? "#0f0" : "#fff";
236
+ ratioSelect.disabled = count > 0;
237
+ if (count > 0) ratioSelect.value = "auto";
238
+ genBtn.innerText = count > 0 ? "EDIT IMAGES" : "GENERATE";
239
+ renderRefPreviews();
240
+ }
241
 
242
+ // Обработка добавления файлов
243
+ async function handleFiles(files) {
244
+ const remainingSlots = 10 - selectedImages.length;
245
+ const filesToAdd = Array.from(files).slice(0, remainingSlots);
246
 
247
+ for (const file of filesToAdd) {
248
  const base64 = await new Promise(resolve => {
249
  const reader = new FileReader();
250
  reader.onload = () => resolve(reader.result);
 
252
  });
253
  selectedImages.push({ url: base64 });
254
  }
255
+ updateEditState();
256
+ }
257
 
258
+ // События для кнопки и инпута
259
+ uploadBtn.onclick = () => fileInput.click();
260
+ fileInput.onchange = (e) => handleFiles(e.target.files);
 
 
 
 
 
 
261
 
262
+ // Drag-and-drop файлов на контейнер или кнопку
263
+ [uploadBtn, refContainer].forEach(el => {
264
+ el.ondragover = (e) => {
265
+ e.preventDefault();
266
+ refContainer.classList.add('drag-over');
267
+ };
268
+ el.ondragleave = () => refContainer.classList.remove('drag-over');
269
+ el.ondrop = (e) => {
270
+ e.preventDefault();
271
+ refContainer.classList.remove('drag-over');
272
+ if (e.dataTransfer.files.length > 0) {
273
+ handleFiles(e.dataTransfer.files);
274
+ }
275
+ };
276
+ });
277
 
278
  renderHistory();
279
  }