Hunterout commited on
Commit
ee4abc0
·
verified ·
1 Parent(s): 231ae6d

Add a button to use the local image generation model that is loaded on the website to generate an image. The prompt for the image is of the most recent message in the users chat with the AI. The image will be displayed in chat as the most recent message.

Browse files
Files changed (3) hide show
  1. index.html +10 -1
  2. script.js +105 -5
  3. style.css +6 -1
index.html CHANGED
@@ -153,8 +153,11 @@
153
  <button class="p-3 rounded-full bg-surface-light hover:bg-gray-700 transition" title="Export Chat">
154
  <i data-feather="download" class="w-5 h-5"></i>
155
  </button>
 
 
 
156
  </div>
157
- </div>
158
  </div>
159
 
160
  <!-- Chat Messages Container -->
@@ -241,6 +244,12 @@
241
  <script src="components/image-generator.js"></script>
242
  <script src="components/local-model.js"></script>
243
  <script src="script.js"></script>
 
 
 
 
 
 
244
  <script>
245
  feather.replace();
246
 
 
153
  <button class="p-3 rounded-full bg-surface-light hover:bg-gray-700 transition" title="Export Chat">
154
  <i data-feather="download" class="w-5 h-5"></i>
155
  </button>
156
+ <button id="generateImageButton" class="p-3 rounded-full bg-surface-light hover:bg-gray-700 transition" title="Generate Image from Last Message">
157
+ <i data-feather="image" class="w-5 h-5"></i>
158
+ </button>
159
  </div>
160
+ </div>
161
  </div>
162
 
163
  <!-- Chat Messages Container -->
 
244
  <script src="components/image-generator.js"></script>
245
  <script src="components/local-model.js"></script>
246
  <script src="script.js"></script>
247
+ <script>
248
+ feather.replace();
249
+
250
+ // Initialize image generation button
251
+ document.getElementById('generateImageButton').addEventListener('click', generateImageFromLastMessage);
252
+ </script>
253
  <script>
254
  feather.replace();
255
 
script.js CHANGED
@@ -15,18 +15,22 @@ document.addEventListener('DOMContentLoaded', function() {
15
  const stopButton = document.getElementById('stopButton');
16
  const sendButton = document.getElementById('sendButton');
17
  const generateImageBtn = document.getElementById('generateImageBtn');
 
18
  const aiStatus = document.getElementById('aiStatus');
19
  const apiStatus = document.getElementById('apiStatus');
20
- // Character counter
21
  messageInput.addEventListener('input', function() {
22
  charCount.textContent = `${this.value.length}/1000`;
23
  });
24
-
25
  // Image generation button
26
  if (generateImageBtn) {
27
  generateImageBtn.addEventListener('click', generateSceneImage);
28
  }
29
- // Send message
 
 
 
 
30
  chatForm.addEventListener('submit', async function(e) {
31
  e.preventDefault();
32
  if (isGenerating) {
@@ -92,7 +96,6 @@ document.addEventListener('DOMContentLoaded', function() {
92
  updateAPIStatus(true, 'Using fallback');
93
  }
94
  }
95
-
96
  // Generate scene image using local model
97
  async function generateSceneImage() {
98
  if (!LOCAL_IMAGE_MODEL) {
@@ -132,7 +135,104 @@ document.addEventListener('DOMContentLoaded', function() {
132
  generator.shadowRoot.querySelector('.generate-btn').click();
133
  }, 500);
134
  }
135
- // Local AI response generation (simulated)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  async function generateLocalAIResponse(characterName, messages, length) {
137
  return new Promise((resolve) => {
138
  // Simulate AI thinking time
 
15
  const stopButton = document.getElementById('stopButton');
16
  const sendButton = document.getElementById('sendButton');
17
  const generateImageBtn = document.getElementById('generateImageBtn');
18
+ const generateImageButton = document.getElementById('generateImageButton');
19
  const aiStatus = document.getElementById('aiStatus');
20
  const apiStatus = document.getElementById('apiStatus');
21
+ // Character counter
22
  messageInput.addEventListener('input', function() {
23
  charCount.textContent = `${this.value.length}/1000`;
24
  });
 
25
  // Image generation button
26
  if (generateImageBtn) {
27
  generateImageBtn.addEventListener('click', generateSceneImage);
28
  }
29
+ // New image generation from last message
30
+ if (generateImageButton) {
31
+ generateImageButton.addEventListener('click', generateImageFromLastMessage);
32
+ }
33
+ // Send message
34
  chatForm.addEventListener('submit', async function(e) {
35
  e.preventDefault();
36
  if (isGenerating) {
 
96
  updateAPIStatus(true, 'Using fallback');
97
  }
98
  }
 
99
  // Generate scene image using local model
100
  async function generateSceneImage() {
101
  if (!LOCAL_IMAGE_MODEL) {
 
135
  generator.shadowRoot.querySelector('.generate-btn').click();
136
  }, 500);
137
  }
138
+
139
+ // Generate image from the most recent message in chat
140
+ async function generateImageFromLastMessage() {
141
+ if (!LOCAL_IMAGE_MODEL) {
142
+ addMessage('system', 'Local image model is not enabled.');
143
+ return;
144
+ }
145
+
146
+ // Get the most recent message content
147
+ const messages = chatMessages.querySelectorAll('.message');
148
+ let lastMessage = '';
149
+
150
+ // Look for the last user or AI message
151
+ for (let i = messages.length - 1; i >= 0; i--) {
152
+ const msg = messages[i];
153
+ const p = msg.querySelector('p');
154
+ if (p && !p.textContent.includes('Generating an image')) {
155
+ lastMessage = p.textContent;
156
+ const isUser = msg.classList.contains('user');
157
+ // Use appropriate sender
158
+ const sender = isUser ? 'You' : document.getElementById('characterName').textContent;
159
+ break;
160
+ }
161
+ }
162
+
163
+ if (!lastMessage.trim()) {
164
+ lastMessage = "A mysterious scene from the conversation";
165
+ }
166
+
167
+ // Add a message indicating image generation is starting
168
+ const thinkingMsg = addMessage('user', `*Generating image for: "${lastMessage.substring(0, 50)}..."*`);
169
+
170
+ // Show typing indicator
171
+ showTyping();
172
+ setGenerating(true);
173
+ updateAPIStatus(true, 'Generating image...');
174
+
175
+ try {
176
+ // Simulate local image generation (using static.photos based on prompt)
177
+ const prompt = lastMessage.substring(0, 100);
178
+ const categories = ['fantasy', 'nature', 'abstract', 'cityscape', 'technology', 'people'];
179
+ const category = categories[Math.floor(Math.random() * categories.length)];
180
+ const seed = Math.floor(Math.random() * 1000);
181
+ const imageUrl = `https://static.photos/${category}/400x300/${seed}`;
182
+
183
+ // Simulate delay
184
+ await new Promise(resolve => setTimeout(resolve, 1500));
185
+
186
+ removeTyping();
187
+ setGenerating(false);
188
+
189
+ // Remove the thinking message
190
+ if (thinkingMsg && thinkingMsg.parentNode) {
191
+ thinkingMsg.parentNode.remove();
192
+ }
193
+
194
+ // Display the generated image in chat
195
+ displayGeneratedImage(imageUrl, prompt);
196
+ updateAPIStatus(true, 'Image generated');
197
+ } catch (error) {
198
+ removeTyping();
199
+ setGenerating(false);
200
+ addMessage('system', `Image generation failed: ${error.message}`);
201
+ updateAPIStatus(false, 'Image failed');
202
+ }
203
+ }
204
+
205
+ // Display generated image in chat
206
+ function displayGeneratedImage(imageUrl, prompt) {
207
+ const messageDiv = document.createElement('div');
208
+ messageDiv.className = 'message ai animate-message-slide mb-6';
209
+
210
+ const time = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
211
+ const avatar = document.querySelector('.bg-surface.rounded-xl.p-5 img')?.src || 'https://static.photos/people/48x48/5';
212
+ const characterName = document.getElementById('characterName').textContent;
213
+
214
+ messageDiv.innerHTML = `
215
+ <div class="flex gap-4">
216
+ <img src="${avatar}" class="w-12 h-12 rounded-full flex-shrink-0">
217
+ <div>
218
+ <div class="font-medium text-primary mb-1">${characterName}</div>
219
+ <div class="bg-surface-light rounded-2xl rounded-tl-none p-4">
220
+ <p>Here's an image inspired by our conversation:</p>
221
+ <div class="image-gen-preview mt-3">
222
+ <img src="${imageUrl}" alt="Generated image" class="rounded-lg" style="max-width: 100%; height: auto;">
223
+ </div>
224
+ <p class="text-sm text-gray-400 mt-2">Prompt: "${prompt.substring(0, 80)}..."</p>
225
+ </div>
226
+ <div class="text-xs text-gray-500 mt-2">${time}</div>
227
+ </div>
228
+ </div>
229
+ `;
230
+
231
+ chatMessages.appendChild(messageDiv);
232
+ chatMessages.scrollTop = chatMessages.scrollHeight;
233
+ feather.replace();
234
+ }
235
+ // Local AI response generation (simulated)
236
  async function generateLocalAIResponse(characterName, messages, length) {
237
  return new Promise((resolve) => {
238
  // Simulate AI thinking time
style.css CHANGED
@@ -114,17 +114,22 @@
114
  align-items: flex-end;
115
  }
116
  }
117
-
118
  /* Image generation preview */
119
  .image-gen-preview {
120
  margin-top: 1rem;
121
  border-radius: 0.75rem;
122
  overflow: hidden;
123
  border: 2px solid #4b5563;
 
124
  }
125
 
126
  .image-gen-preview img {
127
  width: 100%;
128
  height: auto;
129
  display: block;
 
 
 
 
 
130
  }
 
114
  align-items: flex-end;
115
  }
116
  }
 
117
  /* Image generation preview */
118
  .image-gen-preview {
119
  margin-top: 1rem;
120
  border-radius: 0.75rem;
121
  overflow: hidden;
122
  border: 2px solid #4b5563;
123
+ max-width: 400px;
124
  }
125
 
126
  .image-gen-preview img {
127
  width: 100%;
128
  height: auto;
129
  display: block;
130
+ transition: transform 0.3s ease;
131
+ }
132
+
133
+ .image-gen-preview img:hover {
134
+ transform: scale(1.02);
135
  }